麻烦的下载对话框的中文文件名处理.

本文探讨了不同浏览器处理中文文件名时出现的乱码问题,并提供了一种通用解决方案。通过对浏览器类型进行判断,采取不同的编码方式,确保文件名在各种浏览器下正确显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为不同浏览器对head处理的行为不同,所以下载对话框中的中文文件名比较麻烦.没有统一方法,不要以为你看到的是正确的中文,换个浏览器

或换个版本就不一定正确了.

大多数情况下,默认转出UTF-8的字符串是可以的:

String str = "这是一个UTF-8格式编码的中文字符串.dat";

如果不是UTF-8,那么转换到 UTF-8的字符串,大多数时候是有效的.

但是同样是UTF-8字符串,IE的不同版本看到的竟然是不同效果.虽然在contentTyep中已经指明 charset=UTF-8,而且从

客户端进看页面编码也是UTF-8,但不同版本的IE却有的乱码有的正常.

对于IE而言,全部使用url-encode,所有版本都是正确的.这是网上流行的解决方案,但是.....................

对于IE6,限制文件名大约在150个字符以内,一个中文字符UTF8编码为3个byte,再URLEncode成9个byte,所以对于IE6最多不能超过17个中文.所以这个方法不行.

使用俺8年前用的IE下载的乱码无敌大法,当时在IE6以下的所有版本都绝不乱码.今天测试了一下,IE7,IE8,IE9BATE也坚决不乱,又不会有17个中文字符的限制.方法:

将字符串以GB18030编码转换为byte[],然后将每个byte置的成char进行UTF8编码:

byte[] src = "UTF8字符串".getBytes("GB18030");

byte[] buf = new byte[src.length * 3];

int pos = 0;

for(int i=0;i<src.length;i++){

char c = (char)src[i] & 0xFF;

if(c <= 0x007F && c != 0) buf[pos++] = (byte)c;

else if(c > 0x07FF){

buf[pos+2] = (byte) (0x80 | ((c >> 0 ) & 0x3F));

buf[pos+1] = (byte) (0x80 | ((c >>6 ) & 0x3F));

buf[pos+0] = (byte) (0xE0 | ((c >>12 ) & 0x0F));

pos += 3;

}

else{

buf[pos+1] = (byte) (0x80 | ((c >>0) & 0x3F));

buf[pos+0] = (byte) (0xC0 | ((c >>6 ) & 0x1F));

pos += 2;

}

}

return new String(buf,0,pos,"UTF-8");

绝对无敌....................

但是对于FF,url-encode肯定是不行了.直接输出UTF-8,基本上测试过的版本都正确.

但是...................................

不同的容器行为又不样.因为response.setCharacterEncoding只对实体起作用,对头域不起作用,所以对于头域只能手工处理.

比如tomcat,因为它默认是ISO8859_1,你通过response.setCharacterEncoding可以让它对实体部分的处理按你指定的字符集

处理,但

response.setHeader("Content-Disposition","attachment;filename="+str);

无法控制str按指定的字符集处理,所以只能反向转换把UTF-8转成ISO8859_1:

str = new String(str.getBytes("UTF-8"),"ISO8859_1");

response.setHeader("Content-Disposition","attachment;filename="+str);

这样在tomcat输出后,大多数浏览器接收到的 byte[]是UTF-8格式的,能正确处理(IE还是存在版本问题),但这种方案又和容器偶合了.

如果FF不和容器偶合的话,可以进行base64编码,就象IE进行urlencode编码一样.

我KAO,这不是折腾人吗?

那么要尽量做到通用,先要判断浏览器:

String agent = request.getHeader("User-Agent");

if(agent == null) xxxx;

agent = agent.toUpperCase();

if(agent.indexOf("MSIE") != -1) str = URLEncoder.encode(str);

else if(agent.indexOf("FIREFOX") != -1) str = Base64Encoder.encode(str);

else{

............................

}

余下的浏览器怎么办呢?经过测试Opera/Chrome都只能解释UTF-8的中文名.所以

else{

............................

}将这样:

else if(serverTyep.equals("tomcat")){

str = new String(str.getBytes("UTF-8"),"ISO8859_1");

}

else{

//其它容器是否要转码看它默认用什么字符集处理.比如resin就不用任何编码,只要是UTF-8格式的就正确

}

对于服务端的不兼容,其它平台不一定有这个问题.但是对于客户端的不兼容,任何平台都会有这个问题.要针对不同浏览器做不同的处理.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值