動態生成 Excel 文件供瀏覽器下載的注意事項
最近有一個軟件項目,客戶使用中,發現 IE6 會在頁面中打開 Excel 文件,看到亂碼。
經過調查,發現 IE6 有一些比較怪異的工作方式,可以認定為一個 bug.
發生問題時,通過 Firefox 的插件 Firebug , 發現我們在設置 HTTP response 的 header 時候,設置不當:
response.setContentType("text/csv");//出錯在這一行
//以下代碼設置文件名,IE 和非 IE 瀏覽器對于中文文件名處理不同。
String newFileName2 = null;
String userAgent = getUserAgent(request);
if (userAgent.indexOf("MSIE") >= 0) {
URLCodec codec = new URLCodec();
newFileName2 = codec.encode(fileName, "UTF-8");
} else {
newFileName2 = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
}
if (fileName.toLowerCase().indexOf(".htm") < 0) {
response.setHeader("Content-disposition", "attachment; filename=\"" + newFileName2 + "\"");
}
以上代碼,在 IE6/IE9/Firefox5上,正常運行都沒有問題。但是客戶報告 IE6上會有亂碼。
反復測試后,發現:
如果直接在 IE6 瀏覽器地址欄中,輸入
http://localhost/ctms/web_dispatcher/common/export_binary_file?uuid=1e48cbd96d1b4b25b64d5df234680d27
瀏覽器彈出一個“打開”“保存”的對話框,如果這時候選擇“打開”,則會直接在瀏覽器中打開亂碼窗口。相當于這一行代碼失效:
response.setHeader("Content-disposition", "attachment; filename=\"" + newFileName2 + "\"");
但是,如果在頁面中,用 javascript 將當前頁導航到上述網址,則有的機器 IE6 會亂碼,有的機器 IE6 不會亂碼。
經過網上 google 搜索,發現Web 系統動態生成 Excel 文件,在 IE6 下很多人都碰到這個問題。
首先想到,把出錯行改掉:
response.setContentType("text/csv"); ==> response.setContentType("application/vnd.ms-excel");
測試下來,結果:
chrome/firefox5/ie9 都正常,IE6 能正常下載,不會在當前瀏覽器窗口中打開出現亂碼,但取不到 header 中的文件名,而換成從 url 中得到文件名,結果是: export_binary_file.xls。
注意我們的動態網址是:
http://localhost/ctms/web_dispatcher/common/export_binary_file?uuid=1e48cbd96d1b4b25b64d5df234680d27
這很奇怪了。IE6 從 URL 中取文件名的前一半,自動加上 .xls 后綴,拼成新的文件名。
想到我們以后可能會生成 Excel 2007, 或者 Excel 2010 格式的文件,用 "application/vnd.ms-excel" 不合適。
嘗試了其它兩種辦法:
a. response.setContentType("application/octet-stream");
//這個來源于 http://www.ietf.org/rfc/rfc1521.txt
結果:
chrome/firefox5/ie9 都正常, IE6 地址欄輸入網址回車,取不到 header 中的文件名,而換成從 url 中得到文件名,結果是: export_binary_file。相比上面 vnd.ms-excel 的出錯,少了 .xls 這個文件后綴名。
b. response.setContentType("application/force-download");
結果:
chrome/firefox5/ie9 都正常,IE6 地址欄輸入網址回車,結果是: export_binary_file。同 a。
最后結論:
IE6 通過 javascript 導航到動態生成 Excel 的網址,與直接錄入網址,保存時文件名是不同的。這應該是一個bug.
更改response.setContentType("text/csv"); 解決了亂碼問題,無法徹底解決文件名問題。
推測原因:
在動態網頁技術之前的時代,都是靜態網頁,文件下載的網址通常是這樣的:
http://velocityweb.sourceforge.net/zsso_files/zsso-v2.0.1.zip
瀏覽器保存下載文件時,從網址中取文件名,很正常。
而在動態網頁技術時代,網址變成這個樣子:
http://localhost/ctms/web_dispatcher/common/export_binary_file?uuid=1e48cbd96d1b4b25b64d5df234680d27
再從網址中,取文件名,就會出亂子。
IE6 在 javascript 跳轉到上述網址,正常;直接輸入上述網址,文件名不正常,這應該 IE6 沒有更改徹底的緣故。最新的瀏覽器,IE9/Firefox5/chrome,都正常。由于時間關系,我們沒有測試 Firefox/chrome 的早期版本瀏覽器。
我們最后建議這個用戶,安裝一個 firefox 5 了事。

浙公網安備 33010602011771號