Content-Disposition은 파일 다운로드를 처리하는 HTTP 헤더 중 하나다. 웹 서버 응답에 이 헤더를 포함하면 그 내용(보통 사진 등의 파일 데이터)을 웹 브라우저로 바로 보거나 내려받도록 설정할 수 있다. 물론, 다운로드 시에 파일 이름을 지정할 수도 있다. 다만, 이 헤더는 HTTP/1.1 스펙에 기재는 되었으나 표준이 아니다.[각주:1] 그래서인지 웹 브라우저마다 파일 이름을 제각각으로 처리하는 문제가 있다.[각주:2] 이를 해결할 절충안을 찾아보았다.

먼저, Content-Disposition 헤더의 기본 틀은 다음과 같다.

Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="파일 이름.txt"

inlineattachment는 disposition-type이고, filename는 disposition-parm이다.

disposition-type이 inline이면 파일을 웹 브라우저 내에서 볼 수 있고, attachment이면 파일을 내려받을 수 있다. disposition-parm인 filename은 파일을 내려받을 때 파일 이름을 지정한다. 이 값에 ASCII 이외의 문자가 있으면 앞서 말한 문제가 발생한다.[각주:3] 이는 RFC 2231을 참고, filename*에 파일 이름을 인코딩하여 지정하면 해결할 수 있다.[각주:4] 더 나아가서 RFC 6226을 참고, filenamefilename*을 동시에 사용하면 하위 호환성 문제까지 해결할 수 있다. 아래 PHP 스크립트로 파일 이름을 此のファイル test.php로 두고 실험하여 관련 실태를 확인해보자.

웹 브라우저가 파일 이름을 처리한 결과는 다음과 같다.

IE 8IE 11ChromeEdgeFirefox네이버 앱삼성 인터넷OperaDuckDuckGo
A閭ㅳ겗_뺛궊_ㅳ꺂 test.php閭ㅳ겗_뺛궊_ㅳ꺂 test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php
B此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php%E6%AD%A4%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%20test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php
Cdownload_test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.phpdownload_test.php此のファイル test.php此のファイル test.phpdownload_test.php
D閭ㅳ겗_뺛궊_ㅳ꺂 test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.phpdownload_test.php
E此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.php此のファイル test.phpdownload_test.php

웹 브라우저가 파일 이름을 처리한 결과가 此のファイル test.php이면 의도대로 처리했다고 정리하면 다음과 같다.

IE 8IE 11ChromeEdgeFirefox네이버 앱삼성 인터넷OperaDuckDuckGo
AFAILFAILPASSFAILPASSPASSPASSPASSPASS
BPASSPASSPASSPASSFAILPASSPASSPASSPASS
CFAILPASSPASSPASSPASSFAILPASSPASSFAIL
DFAILPASSPASSPASSPASSPASSPASSPASSFAIL
EPASSPASSPASSPASSPASSPASSPASSPASSFAIL

유명한 웹 브라우저들은 E: UTF-8 URL Encoded + RFC 2231로 파일 이름 처리를 잘 한다고 보면 되겠다. 그러니 파일을 내려받을 때 파일 이름을 지정하려면 아래 PHP 코드를 이용하자!

$encodedFilename = rawurlencode($filename);
header("Content-Disposition: attachment; filename=\"$encodedFilename\"; filename*=UTF-8''$encodedFilename");

참고

https://fastmail.blog/2011/06/24/download-non-english-filenames/

번외

테스트 중 발견했는데, 네이버 앱은 파일 다운로드를 특이하게 처리한다. 웹 서버 로그로는 파일을 한 번에 받지 않고, 두 번 탐색 후 내려받은 것으로 보인다.

[07/Aug/2018:01:34:22 +0000] "GET /download_test.php?t=A%3A%20UTF-8%20Raw HTTP/1.1" 200 "Mozilla/5.0 (Linux; Android 8.1; Pixel Build/OPM4.171019.021.P1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Crosswalk/20.50.533.55 Mobile Safari/537.36 NAVER(inapp; search; 590; 8.8.3)" "-"
[07/Aug/2018:01:34:22 +0000] "GET /download_test.php?t=A%3A%20UTF-8%20Raw HTTP/1.1" 200 "Dalvik/2.1.0 (Linux; U; Android 8.1.0; Pixel Build/OPM4.171019.021.P1)" "-"

비트맵 미러에 사람 인증을 적용하고 네이버 앱으로 비트맵을 받지 못하는 문제가 있는데, 이게 그 이유겠구나~~

  1. 뽀또맛콜라
    군대는 잘갔다오셨는지요 ㅋㅋㅋ 급식사이트 잘쓰고있습니다! !
    최근에 리뉴얼되었더군요!!

Name __

Password __

Link (Your Website)

Comment