处理过程

根据IE的F12中的log提示,是因为http头信息中的编码替换了html文件中的编码。我最初的思路是设置Tomcat默认编码,但是我发现我已经在Server.xml中设置过,想到这里我想到了上篇文章的文件重命名的问题,准备去写个filter去修改http响应头,但是我突然明白,SpringMVC应该会处理过,但是为什么无效呢,这种成熟的框架不应该会有bug存在,于是我尝试在SpringMVC的xml中配置SourceHttpMessageConverter等转换器,都无效。

发现原因

后来发现web.xml是配置了编码处理的, 内容如下:

//第一个工具类中的下载方法:
/**
* 下载
* @param request
* @param response
* @param fileName
* @param downLoadPath
* @param contentType
* @throws IOException
* @throws Exception
*/
public static void download(HttpServletRequest request,HttpServletResponse response,String fileName,String downLoadPath,String contentType) throws IOException{
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
long fileLength = new File(downLoadPath).length(); response.setContentType(contentType);
response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));
response.setHeader("Content-Length", String.valueOf(fileLength)); bis = new BufferedInputStream(new FileInputStream(downLoadPath));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))){
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
} //第二个工具类中的主要关键代码:
String filename = null;
if(request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0){
filename = URLEncoder.encode(name, "UTF-8");
}else{
filename = new String(name.getBytes(),"ISO8859-1");
}
response.setHeader("Content-Disposition", "attachment;filename=" + filename);

为了知道这样子到底会有什么问题,是不是只有IE会出现问题,其他浏览器会不会有其他的问题。抱着这些疑问,我找来了目前市面上用户量较多的几款主流的浏览器进行测试,包括:两个不同版本的IE11,Chrome,FireFox,Opera,360浏览器,搜狗浏览器等。经过我对下载的文件的各种文件名称使劲地折腾主要发现以下几个问题:

1.两个IE11在使用第一个方法下载文件时中文文件名都会乱码,而使用第二个方法下载时其中一个IE11中文不会乱码,另一个IE11则会乱码; 
2.文件名中存在空格时两个IE11浏览器下载下来文件文件名空格会变成+号,其他浏览器没有这个问题; 
3.火狐浏览器下载时遇到文件名中有空格时下载下来的文件的文件名第一个空格后面的文字都会丢失。

经过一番折腾发现原来我们大国产浏览器还是可以的,没有发现明显的问题;233333。 
那么这些问题该如何解决呢?首先第一个问题,显然第一段代码并没有将IE浏览器过滤出来对文件名进行单独编码,而是统一采用ISO8859-1编码,这样如果文件名是英文的IE就不会出现任何问题,中文就会出现乱码,其他语言文字则不清楚,其他几款浏览器则没有任何问题,都能兼容。那第二段代码则首先对Http请求头中User-Agent参数进行了判断,通过MISE字段将IE浏览器过滤出来,对文件名进行单独UTF-8编码,所以中文文件名不会乱码了。那么问题来了,为什么两个IE11浏览器,其中一个中文不乱码,而另一个却乱码呢。经过对程序的单步调试,发现那个中文乱码的IE在进入这个方法后程序并没有跳入对文件名进行utf-8编码的方法,而是进入了else下面的那一行代码。那也就是说两个IE11的User-Agent参数中,其中一个有MISE关键字,而另一个则没有。通过查阅资料,原来微软在IE11之后在浏览器的User-Agent参数中去掉了MISE关键字,导致的结果是使用低版本的IE下载中文文件名文件时不会乱码,而采用大部分IE11及以上版本,包括Edge等都会出现中文乱码现象。难怪大家老是说IE很坑呢,IE在这种地方都埋好了坑,等着我们去踩,我也是醉了。

浏览器的User-Agent这个参数主要包含了一些操作系统版本,浏览器版本、内核等信息。

那个下载文件中文会乱码的IE的User-Agent参数如下: 
IE11:Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko;

显然里面并没有MISE关键字,那么怎么办呢?通过对比几款不同浏览器的User-Agent参数,发现这里面有一个Trident关键字比较特别,是其他浏览器所没有的,那么解决方案来了,我们可以通过Trident关键字来进行对部分IE11的过滤了;

那么针对第二个问题中出现的空格变+号,则是因为URLEncoder函数在对字符串进行转码后将空格替换成了+号,IE就直接把+号显示出来了,解决方法是在对文件名进行转码后,使用replace方法将+号替换为%20即可,浏览器会将%20转换成空格输出。

对于第三个问题则是因为代码在set响应头时Content-Disposition参数的attachment;filename=等号后面文件名字符串没有用双引号括起来,火狐浏览器对于遇到文件名有空格时认为空格前的字符是一个完整的字符串,故下载下来文件时文件名就只剩下空格前的那几个字了。解决方法是在filename两边加上双引号并加反斜杠转义。具体的最终解决这些问题后经过测试兼容性比较好的代码如下:

public static void download(HttpServletRequest request, HttpServletResponse response, String fileName, String downLoadPath, String contenType) throws Exception {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8"); BufferedInputStream bis = null;
BufferedOutputStream bos = null; long fileLength = new File(downLoadPath).length(); response.setContentType(contenType); String header = request.getHeader("User-Agent").toUpperCase();
if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
fileName = URLEncoder.encode(fileName, "utf-8");
fileName = fileName.replace("+", "%20"); //IE下载文件名空格变+号问题
} else {
fileName = new String(fileName.getBytes(), "ISO8859-1");
} response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");
response.setHeader("Content-Length", String.valueOf(fileLength)); bis = new BufferedInputStream(new FileInputStream(downLoadPath));
bos = new BufferedOutputStream(response.getOutputStream()); byte[] buff = new byte[2048];
int bytesRead; while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
}

或者,使用下面这段代码也可以处理乱问题,代码如下:

try {
String fileName = attachmentFile.originalName();
String userAgent = request.getHeader("user-agent").toLowerCase();
if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {
// win10 ie edge 浏览器 和其他系统的ie
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
//其他的浏览器
fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
}
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
String path = attachmentFile.path();
InputStream inputStream = new FileInputStream(new File(path)); OutputStream os = response.getOutputStream();
byte[] b = new byte[2048];
int length;
while ((length = inputStream.read(b)) > 0) {
os.write(b, 0, length);
} // 这里主要关闭流。
os.close(); inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} 获取更多精彩内容,学习资料,视频等,请关注微信公众号【程序员Style】,回复关键字即可。

IE浏览器下载文件中文文件名乱码问题解决的更多相关文章

  1. nodejs adm-zip 解压文件 中文文件名乱码 问题解决

    修改需要使用到iconv-lite包 (npm安装即可),修改 zipEntry.js 文件中的 entryName 方法 var iconv = require('iconv-lite'); var ...

  2. ie浏览器下载文件时文件名乱码

    做一个文件下载功能时,用ie浏览器下载时文件名乱码,火狐和谷歌正常,修改后ie显示正常,修改方法如下: @RequestMapping(value = "fileDownload" ...

  3. Java 使用IE浏览器下载文件,文件名乱码问题

    使用Servlet实现文件下载功能时,使用IE下载出现文件名乱码; 网上常见的解决办法是通过"user-agen"来判断浏览器: if (req.getHeader("u ...

  4. 解决PHP在IE中下载文件,中文文件名乱码问题

    if( stripos($_SERVER['HTTP_USER_AGENT'], 'MSIE')!==false ) $filename = urlencode( $filename ); // 输入 ...

  5. Java使用IE浏览器下载文件,文件名乱码问题

    String userAgent = request.getHeader("user-agent").toLowerCase(); if (userAgent.contains(& ...

  6. 平板电脑与火狐浏览器下载excel中文文件名乱码

    fileName = new String(fileName.getBytes("utf-8"), "iso8859-1");//兼容火狐.ie.平板 resp ...

  7. 火狐浏览器下载文件中文乱码,文件名中的空格变加号("+")的问题

    解决一下问题: 1.火狐浏览器下载文件,中文变乱码 2.IE浏览器下载文件,丢失文件扩展名或强制扩展名为".txt" 3.浏览器下载文件,文件名中的空格变成加号("+&q ...

  8. HTTP 下载文件中文文件名在 Firefox 下乱码问题

    转自:http://www.imhdr.com/991/ HTTP 下载文件,中文文件名在 Firefox 下乱码问题 最近帮助一同事解决 HTTP 下载文件时,中文文件名在 Firefox 下乱码的 ...

  9. C#中解决Response.AddHeader("Content-Disposition", "attachment; filename=" + filename)下载文件时文件名乱码的问题

    问题:下载文件时文件名乱码怎么解决? 在C#写后台代码过程中,经常遇到下载文件出现文件名乱码的问题,在网上找了很多方法,总是存在浏览器不兼容的问题,当IE浏览器不乱码时,火狐浏览器就会乱码,后来经过反 ...

随机推荐

  1. String.slice

    String.slice(start, end)start从字符串的哪个index开始截取 默认值0 如果为负值,则从字符串的尾部向前倒推indexend到从字符串的哪个index结束截取 默认值st ...

  2. 修改从Maven中心仓库下载到本地的jar包的默认存储位置及远程仓库

    从Maven中心仓库下载到本地的jar包的默认存放在”${user.home}/.m2/repository”中,${user.home}表示当前登录系统的用户目录(如"C:\Users\g ...

  3. 疯狂补贴的4G+  会是又一个资费陷阱吗?

     会是又一个资费陷阱吗?" title="疯狂补贴的4G+  会是又一个资费陷阱吗?"> 常言说得好,防火防盗防运营商--具有垄断性质的中国移动.联通.电信三大基础 ...

  4. Leetcode 703题数据流中的第K大元素(Kth Largest Element in a Stream)Java语言求解

    题目链接 https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/ 题目内容 设计一个找到数据流中第K大元素的类(class) ...

  5. 什么是HDFS?算了,告诉你也不懂。

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 上一篇已经讲解了「大数据入门」的相关基础概念和知 ...

  6. 超全!python的文件和目录操作总结

    文件的基本读写 path = r'C:\Users\Brady\Documents\tmp' with open(path + r'\demo.txt', 'r', encoding='utf-8') ...

  7. App崩溃监控

    常见马虎导致崩溃 1 数组越界: 2 多线程问题,在子线程刷新UI: 3 主线程无响应,主线程超过系统规定的时间没有响应,就会被watchdog杀掉: 4 野指针: 崩溃信息的收集却并没有那么简单.因 ...

  8. k3s原理分析丨如何搞定k3s node注册失败问题

    前 言 面向边缘的轻量级K8S发行版k3s于去年2月底发布后,备受关注,在发布后的10个月时间里,Github Star达11,000颗.于去年11月中旬已经GA.但正如你所知,没有一个产品是十全十美 ...

  9. C#编程_单线程IP地址解析

    单线程IP地址解析 目标程序 界面如下图 ​ 设计方法:完成单个IP地址解析,循环调用方法,完成扫描. 注意用stopwatch计算时间. 实现思路 先知道怎么解析一个单个的IP地址. 用循环的方法解 ...

  10. 前端每日实战:85# 视频演示如何用纯 CSS 创作一个小球反弹的动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OwWROO 可交互视频 此视频是可 ...