[browser] HTTP에서 Content-Disposition 헤더의 파일 이름 매개 변수를 인코딩하는 방법은 무엇입니까?

웹 브라우저에서 직접 렌더링 하지 않고 자원을 강제로 다운로드 하려는 웹 응용 프로그램 은 다음 형식의 HTTP 응답으로 헤더를 발행합니다 .Content-Disposition

Content-Disposition: attachment; filename=FILENAME

filename매개 변수는 브라우저가 자원을 다운로드 한 파일의 이름을 제안하는 데 사용할 수 있습니다. 그러나 RFC 2183 (Content-Disposition)은 2.3 (파일 이름 매개 변수) 섹션 에 파일 이름에 US-ASCII 문자 만 사용할 수 있다고 명시되어 있습니다.

현재 [RFC 2045] 문법은 매개 변수 값 (및 Content-Disposition 파일 이름)을 US-ASCII로 제한합니다. 파일 이름에 임의의 문자 집합을 허용하는 것이 바람직하지만이 문서에서는 필요한 메커니즘을 정의하지 않습니다.

그럼에도 불구하고 오늘날 가장 널리 사용되는 웹 브라우저는 미국 이외의 ASCII 문자가 아닌 (표준이 없기 때문에) 파일 이름의 인코딩 체계 및 문자 세트 사양에 동의하지 않는 것으로 보입니다. 그렇다면 파일 이름 “naïvefile”(따옴표없이 세 번째 문자가 U + 00EF 인 경우)을 Content-Disposition 헤더로 인코딩해야하는 경우 인기있는 브라우저에서 사용하는 다양한 체계와 인코딩은 무엇입니까?

이 질문의 목적 상 인기있는 브라우저 는 다음과 같습니다.

  • Firefox
  • 인터넷 익스플로러
  • 원정 여행
  • 구글 크롬
  • 오페라


답변

제안 된 RFC 5987 , “HTTP (Hypertext Transfer Protocol) 헤더 필드 매개 변수에 대한 문자 세트 및 언어 인코딩” 에서 브라우저 테스트 및 이전 버전과의 호환성에 대한 링크를 포함하여 이에 대한 설명이 있습니다.

RFC 2183 은 이러한 헤더가 RFC 2231에 의해 폐기 된 RFC 2184 에 따라 인코딩되어야하며 , 상기 RFC 초안에 포함된다.


답변

나는 이것이 오래된 게시물이라는 것을 알고 있지만 여전히 관련이 있습니다. 현대 브라우저는 rfc5987을 지원하며 utf-8 인코딩, 백분율 인코딩 (URL 인코딩)을 허용합니다. 그런 다음 Naïve file.txt는 다음과 같습니다.

Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt

Safari (5)는이를 지원하지 않습니다. 대신 utf-8로 인코딩 된 헤더에 파일 이름을 직접 쓰는 Safari 표준을 사용해야합니다.

Content-Disposition: attachment; filename=Naïve file.txt

IE8 및 그 이전 버전도 지원하지 않으며 utf-8 인코딩의 IE 표준, 백분율 인코딩을 사용해야합니다.

Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt

ASP.Net에서는 다음 코드를 사용합니다.

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
    contentDisposition = "attachment; filename=" + fileName;
else
    contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5를 사용하여 위의 테스트를 수행했습니다.

2013 년 11 월 업데이트 :

현재 사용중인 코드는 다음과 같습니다. 여전히 IE8을 지원해야하므로 첫 번째 부분을 제거 할 수 없습니다. Android의 브라우저는 내장 된 Android 다운로드 관리자를 사용하며 표준 방식으로 파일 이름을 안정적으로 구문 분석 할 수 없습니다.

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
    contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
    contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

위의 파일은 다음 파일 이름을 사용하여 IE7-11, Chrome 32, Opera 12, FF25, Safari 6에서 테스트되었습니다. 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§ !! ^ ~ ‘-_,;. txt

IE7에서는 일부 문자에서 작동하지만 일부 문자에서는 작동하지 않습니다. 그러나 오늘날 누가 IE7에 관심이 있습니까?

이것은 Android의 안전한 파일 이름을 생성하는 데 사용하는 기능입니다. Android에서 지원되는 문자를 모르지만 이러한 문자가 제대로 작동하는지 테스트했습니다.

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
    char[] newFileName = fileName.ToCharArray();
    for (int i = 0; i < newFileName.Length; i++)
    {
        if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
            newFileName[i] = '_';
    }
    return new string(newFileName);
}

@TomZ : IE7과 IE8에서 테스트했으며 아포스트로피 ( ‘)를 벗어날 필요가 없다는 것이 밝혀졌습니다. 실패한 예가 있습니까?

@Dave Van den Eynde : RFC6266에 따라 두 줄의 파일 이름을 한 줄에 결합하면 Android 및 IE7 + 8을 제외하고 작동하며 코드를 업데이트했습니다. 제안 해 주셔서 감사합니다.

@Thilo : GoodReader 또는 다른 비 브라우저에 대해서는 전혀 모른다. 안드로이드 접근법을 사용하면 운이 좋을 수도 있습니다.

@ Alex Zhukovskiy : 왜 그런지는 모르겠지만 Connect 에서 논의한 것처럼 끔찍하게 작동하지 않는 것 같습니다.


답변

  • 에서 비 ASCII 이름을 인코딩하는 상호 운용 가능한 방법은 없습니다 Content-Disposition. 브라우저 호환성은 엉망 입니다.

  • 이론적으로 올바른 구문 UTF-8에서의 사용은 Content-Disposition매우 이상한 : filename*=UTF-8''foo%c3%a4(예, 중간에 비어있는 작은 따옴표를 제외한 별표 및 따옴표있어 그)

  • 이 헤더는 다소 표준이 아닙니다 ( HTTP / 1.1 사양은 그 존재를 인정 하지만 클라이언트가 그것을 지원할 필요는 없습니다).

간단하고 매우 강력한 대안 이 있습니다 . 원하는 파일 이름이 포함 된 URL을 사용하십시오 .

마지막 슬래시 뒤의 이름이 원하는 이름이면 추가 헤더가 필요하지 않습니다!

이 트릭은 작동합니다.

/real_script.php/fake_filename.doc

그리고 서버가 URL 재 작성을 지원하는 경우 (예 : mod_rewriteApache) 스크립트 부분을 완전히 숨길 수 있습니다.

URL의 문자는 바이트 단위로 urlencoded 된 UTF-8 형식이어야합니다.

/mot%C3%B6rhead   # motörhead


답변

RFC 6266 은“ HTTP (Hypertext Transfer Protocol)에서 콘텐츠 처리 헤더 필드 사용 ”에 대해 설명합니다 . 그 인용 :

6. 국제화 고려 사항

[ RFC5987 ]에 정의 된 인코딩을 사용하여 ” filename*“매개 변수 ( 4.3 절 )를 사용하면 서버가 ISO-8859-1 문자 세트 외부에서 문자를 전송하고 선택적으로 사용중인 언어를 지정할 수 있습니다.

그리고 그들의 예제 섹션에서 :

이 예제는 위의 예제와 동일하지만 RFC 5987을 구현하지 않는 사용자 에이전트와의 호환성을 위해 “filename”매개 변수를 추가합니다
.

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

참고 : RFC 5987 인코딩을 지원하지 않는 사용자 에이전트 는“ filename*”다음에 발생하면 “ ”를 무시 합니다 filename.

에서 부록 D 증가 상호 운용성에 대한 제안의 긴 목록도 있습니다. 또한 구현을 비교하는 사이트를 가리 킵니다 . 공통 파일 이름에 적합한 현재 전체 패스 테스트에는 다음이 포함됩니다.

  • attwithisofnplain : 큰 따옴표가 있고 인코딩이없는 일반 ISO-8859-1 파일 이름. 파일 이름은 모두 ISO-8859-1이며 최소한 16 진수 앞에는 백분율 기호를 포함하지 않습니다.
  • attfnboth : 위에서 설명한 순서대로 두 개의 매개 변수. IE8은“ filename”매개 변수를 사용하지만 대부분의 브라우저에서 대부분의 파일 이름에 대해 작동해야합니다 .

즉, RFC 5987 차례 참조에서 RFC 2231 의 실제 형식을 설명합니다. 2231은 주로 메일 용이며 5987은 HTTP 헤더에 사용될 부분을 알려줍니다. RFC 2388 ( 특히 섹션 4.4 ) 및 HTML 5 초안 에 의해 관리되는 multipart/form-dataHTTP 본문 내부에서 사용되는 MIME 헤더와 이것을 혼동하지 마십시오 .


답변

Jim 이 그의 답변에서 언급 한 RFC 초안 에서 링크 된 다음 문서 는이 질문에 대해 자세히 설명하고 여기에서 직접 참고할 가치가 있습니다.

HTTP 콘텐츠 처리 헤더 및 RFC 2231/2047 인코딩에 대한 테스트 사례


답변

asp.net mvc2에서 나는 다음과 같은 것을 사용한다 :

return File(
    tempFile
    , "application/octet-stream"
    , HttpUtility.UrlPathEncode(fileName)
    );

mvc (2)를 사용하지 않으면 다음을 사용하여 파일 이름을 인코딩 할 수 있습니다.

HttpUtility.UrlPathEncode(fileName)


답변

파일 이름을 큰 따옴표로 묶으십시오. 나를 위해 문제를 해결했습니다. 이처럼 :

Content-Disposition: attachment; filename="My Report.doc"

http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download

여러 옵션을 테스트했습니다. 브라우저는 사양을 지원하지 않으며 다르게 행동합니다. 큰 따옴표가 가장 좋은 옵션이라고 생각합니다.