この日記は私的なものであり所属会社の見解とは無関係です。 GitHub: takahashikzn

ファイル名に半角空白を含むファイルをダウンロードするとファイル名が化ける

ファイル名に半角空白を含むファイルをダウンロードすると
ファイル名が化けるというバグに出くわしました。


例えば、

a b c.txt

というファイルをダウンロードしようとすると、

a+b+c.txt

となってしまいます。

原因

Servletでダウンロードさせるファイル名を指定するときには
次のようにするのが一般的です(IE, Chrome)。

HttpServletRequest req = ...;

String headerValue = String.format("attachment; filename=%s", URLEncoder.encode(fileName));

req.addHeader("Content-Disposition", headerValue);


このとき、URLEncoder#encodeした結果であるheaderValueの値が

a+b+c.txt

となってしまっていることが原因です。


但しコレ、あながち間違いとも言えない。
なぜならURLエンコードの仕様上、半角空白を"+"で表すことが許されているからです。(MUSTかどうかは知らない...RFCに載っているはず)

解決方法

次のようにすればOK。

HttpServletRequest req = ...;

String encodedFileName = URLEncoder.encode(originalFileName).replace("+", "%20");

req.addHeader(
    "Content-Disposition", 
    "attachment; filename=" + encodedFileName);

これで半角空白が化けずにダウンロード可能です。
しつこいようですがIEChrome限定です。ご注意を。


Firefoxの場合、

上記のままやると文字化けします。Content-Dispositionの書き方が違うことが原因。
RFC的に正しい手順である、MIMEエンコーディングする必要アリ。