最近有一个软件项目,客户使用中,发现 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 了事。