星期三, 十二月 20, 2006

下载文件的中文文件名问题


为何需要自己写下载程序,基本上都是出于安全考虑,而不是基于性能考虑,这里就不详细描述了,只写下在其中遇到的中文文件名问题。


网上有很多这方面资料,基本上都沾边,又不完整。


目前发现主要问题就是IE识别的是utf8编码,而firefox之类的浏览器识别的是ISO8859-1编码。还有一个就是空格的处理,不同浏览器是不一样处理的。另外据说老版本IE有150个字符的问题,经测试在IE6或更高版本中,已经可以自动截断了,这里就不再写处理办法了,其实如果需要处理就是把文件名自己截短即可。


String agentName = request.getHeader("user-agent");
boolean agentBeIE = (agentName!=null && agentName.indexOf("MSIE")>=0);


if (agentBeIE) {
encoding = "UTF-8";
attachFilename = java.net.URLEncoder.encode(saveas_filename, encoding);
attachFilename = attachFilename.replaceAll("\\+", "%20");
}
else {
encoding = "ISO8859_1";
attachFilename = new String(saveas_filename.getBytes("UTF-8"),encoding);
}


response.reset();
response.setCharacterEncoding(encoding);//似乎不起作用
response.setHeader("Content-Type",file_contenttype + ";charset=" + encoding);
response.setHeader("Content-Disposition",(isOnLine?"inline; ":"attachment; ")+"filename=\"" +attachFilename +"\"");
response.setHeader("Cache-Control", "no-cache,must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setContentLength((int) filesize);


ServletOutputStream sout = response.getOutputStream();
byte[] buf = new byte[0x40000]; //256K=2^18=4*2^16
int nNumber=0;
long nTotalRead=0;
while ((nNumber = is.read(buf)) != -1)
{
sout.write(buf, 0, nNumber);
nTotalRead += nNumber;
}
sout.flush(); //输入完毕,清除缓冲
sout.close(); //关闭输出
response.flushBuffer();