問題背景: 導出報表,下載文件後有文件名亂碼的情況。問題修復多次後仍有特定環境下亂碼的情況,以下貼出幾次歷史修改的核心代碼
response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(exportFileName.getBytes("GBK"), "ISO-8859-1") + "\"");
問題:臺灣windows操作系統環境下(系統語環境編碼:950(big5)) 導出文件文件名亂碼,GBK改成big5雖然繁體中文操作系統訪問不亂,但簡體中文操作系統(GBK)環境不行。
response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(exportFileName.getBytes("UTF-8"), "ISO-8859-1") + "\"");
問題:chrome瀏覽器不亂碼,但IE不行
完美解決方案:
response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedName + "\";filename*=utf-8''" + encodedName);
此處的encodedName 要求對文件名URL編碼(URLEncoder.encode(文件名))
代碼截取:
private void setResponseHeaders(HttpServletResponse response, String exportFileName)
throws UnsupportedEncodingException {
String mimeType = MimeUtils.getFileMimeType(exportFileName);
if (StringUtils.isNotBlank(mimeType)) {
response.setContentType(mimeType);
}
String charset = "UTF-8";
// 2011年 RFC 6266 發佈,正式將 Content-Disposition 納入 HTTP 標準,並再次強調了 RFC 5987
// 中多語言編碼的方法,並給出了一個範例用於解決向後兼容的問題
// Content-Disposition:
// attachment;filename="encoded_text";filename*=utf-8''encoded_text
// Firefox 、 Chrome 、 Opera 、 Safari 等瀏覽器,都支持新標準規定的 filename*
// ,IE支持filename="encoded_text"
String encodedName = URLEncoder.encode(exportFileName, charset);
response.setHeader("Content-Disposition",
"attachment;filename=\"" + encodedName + "\";filename*=utf-8''" + encodedName);
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setDateHeader("Expires", (System.currentTimeMillis() + MILLISECOND));
}
以下是原理,來自互聯網:
2011年 RFC 6266 發佈,正式將 Content-Disposition 納入 HTTP 標準,並再次強調了 RFC 5987
中多語言編碼的方法,並給出了一個範例用於解決向後兼容的問題
Content-Disposition : attachment;filename=“encoded_text”;filename*=utf-8’'encoded_text
Firefox 、 Chrome 、 Opera 、 Safari 等瀏覽器,都支持新標準規定的 filename*,IE支持filename=“encoded_text”
參考資料:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
https://tools.ietf.org/html/rfc6266