采用Struts2提供的文件下载机制时,如果要下载的文件的的名字是中文的话,就会出现乱码问题。解决办法如下(只截取部分代码):
UserFavoritesAttachment u = (UserFavoritesAttachment) getSession().get(UserFavoritesAttachment.class,Long.parseLong(fpid));
String fileName = u.getFilename();//要提供fileName 的get,set方法,因为我的文件路径及文件名是从数据库中获得,故通过这种方式获得文件名(中文)
如果直接使用这个fileName的话,就会出现中文乱码,即使你现在把它的值打出来是正确的。因此这里要转码一次,
try {
fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
网上有好多地方提到这种转码方式,
try {
fileName = new String(fileName.getBytes(),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
本人试过这种方式,还是会出现乱码,故建议采用第一种方法,实在不行,两种都试一下,程序重在调试嘛!
如果用jsp提供的方式下载(原始的,没有封装的),也只需把fileName砖码一次,即
try {
fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
response.setHeader("content-disposition", "attachment;filename=" + fileName);
如果文件名是从前台视图页面(jsp页面)通过url参数传到action中去的话,jsp页面中就要编码两次,action中解码一次。代码如下:
jsp页面:
function fun(){
var name1 = encodeURI("张三");
alert(name1);
var name2 = encodeURI(name1);
alert(name2);
window.location.href="encode.action?name="+name2;
}
<a href="javascript:fun()">点击下载</a>
action代码:
private String name;
public void setName(String name) {
try {
name=java.net.URLDecoder.decode(name, "utf-8");
} catch (UnsupportedEncodingException e) { e.printStackTrace();
}
this.name = name;
}
public String getName() {
return name;
}
读者可以debug跟踪一下name,或者输出name,就会发现set方法中的name是正常的。
为什么要前台页面编码两次,后台代码要解码一次了?因为汉字是不能在url中直接传参过去的,必须要经过编码,js中encodeURI()方法会对汉字进行utf-8编码;首先会找到汉字在utf-8编码在内存中的十六进制格式的表示,并在每个十六进制字节前加上%,“张三”用encodeURI()方法编码一次之后是%D5%C5%C8%FD,用encodeURI()编码第二次以后是%25D5%25C5%25C8%25FD,action获取这个参数的时候已经把传过来的值用iso-8859-1的形式解码了一次,因为tomcat默认的编码方式是iso-8859-1,但服务器的这次解码对于像%25D5%25C5%25C8%25FD这样的数据来说,与手动用utf-8方式解码的效果一样,结果都是%D5%C5%C8%FD(把%25换成了%),然后在手动解码一次,即action代码中的name=java.net.URLDecoder.decode(name, "utf-8"),就变成汉字了。