转:java下载文件时文件名乱码 – 智云一二三科技

方案一:将文件名编码为Unicode

fileName = URLEncoder.encode(fileName, "UTF-8");

文件名会转换为Unicode编码,在IE浏览器下测试正常,但是Firefox浏览器下测试得到的文件名是没有解码的Unicode。

方案二:将文件名编码为ISO-8859-1

fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");

这种方式在IE下和Firefox下均可以得到中文文件名的文件。但如果文件名中带有空格,Firefox会从空格处截断文件名,需要在编码之前将文件名中的空格替换成下划线之类的可见字符。

fileName = new String(fileName.replace(" ", "_").getBytes("UTF-8"), "ISO-8859-1");

方案三:浏览器不兼容问题

在Java的web开发中,文件下载功能的文件名文件名乱码问题是经常遇到的。对于这个问题,不同的浏览器,解决的方法不太一样。

IE的话,通过URLEncoder对filename进行UTF8编码,而其他的浏览器(firefox、chrome、safari、opera),则要通过字节转换成ISO8859-1了。

if (request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {
    filename = URLEncoder.encode(filename, "UTF-8");
} else {    
    filename = new String(filename.getBytes("UTF-8"), "ISO8859-1");
}

关于设置ISO8859-1编码文件名

转:下载文件设置header的filename要用ISO8859-1编码的原因 - 走看看

 提取出来最核心的一点,filename=new String("中文文件名".getBytes("utf-8"), "ISO8859-1");

先说为什么使用 ISO8859-1 编码,这个主要是由于http协议,http header头要求其内容必须为iso8859-1编码,所以我们最终要把其编码为 ISO8859-1 编码的字符串;因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题

但是前面为什么不直接使用 "中文文件名".getBytes("ISO8859-1"); 这样的代码呢?

因为ISO8859-1编码的编码表中,根本就没有包含汉字字符,当然也就无法通过"中文文件名".getBytes("ISO8859-1");来得到正确的“中文文件名”在ISO8859-1中的编码值了,所以再通过new String()来还原就无从谈起了。 

所以先通过 "中文文件名".getBytes("utf-8") 获取其 byte[] 字节,让其按照字节来编码,即在使用 new String("中文文件名".getBytes("utf-8"), "ISO8859-1") 将其重新组成一个字符串,传送给浏览器。

String.getBytes(String decode)

方法会根据指定的decode编码返回某字符串在该编码下的byte数组

new String(byte[], decode)

使用decode指定的编码来将byte[]解析成字符串。

String fileName = "测试";
fileName = new String(fileName.getBytes(), "ISO8859-1");
System.out.println("模拟传输:" + fileName); 
//使用iso8859-1编码后 fileName 在这些字符传递到目的地后,目的地程序再通过相反的方式
fileName = new String(fileName.getBytes("ISO8859-1"));
System.out.println("前端得到的文件名:" + fileName);

 结果:

模拟传输:æµè¯
前端得到的文件名:测试

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐