IE浏览器下载文件中文文件名乱码问题解决
处理过程
根据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();}
IE浏览器下载文件中文文件名乱码问题解决相关推荐
- 使用IE浏览器下载文件,文件名乱码问题
实现文件下载功能时,使用IE下载出现文件名乱码不能通过以下方式判断了 if (req.getHeader("user-agent").toLowerCase().contains( ...
- 解决各大浏览器下载文件,文件名乱码的问题
最近做项目,采用Spring MVC做控制层,下载文件的文件名总是在主流浏览器上显示乱码,Firfox不是乱码了,IE下又成了乱码.也是烦,IE总是独树一帜,没办法,只能让程序去适应,在网上也搜索了很 ...
- 火狐浏览器下载文件时文件名乱码问题的解决
火狐浏览器在微信网页版或其他网站中下载文件时,存在文件名乱码的问题,搜索了很多解决办法,写的都比较复杂,不适合我这种不懂代码的人.后来发现火狐浏览器附加组件addons上可以搜到解决此问题的组件,就是 ...
- 解决浏览器下载文件 中文名字乱码解决
浏览器能正确识别的编码格式,只要按照这样的编码来设置对应的Content-Disposition,那么应该就不会出现中文文件名的乱码问题了. 首先,文件名作为参数保存Content-Dispositi ...
- Linux火狐浏览器下载文件时文件名乱码
火狐下载时文件名会乱码,其他浏览器如360.奇安信.扣扣都是正常的! 本文转自https://blog.csdn.net/tengqingyong/article/details/79943971?u ...
- ie浏览器打开aspx文件乱码_ie浏览器下载文件时文件名乱码
做一个文件下载功能时,用ie浏览器下载时文件名乱码,火狐和谷歌正常,修改后ie显示正常,修改方法如下: @RequestMapping(value = "fileDownload" ...
- Java 使用IE浏览器下载文件,文件名乱码问题
使用Servlet实现文件下载功能时,使用IE下载出现文件名乱码; 网上常见的解决办法是通过"user-agen"来判断浏览器: if (req.getHeader("u ...
- 解决IE浏览器下载文件,文件名乱码问题(浏览器历史介绍)
这个问题,CS开发模式总会遇到过.在此详细记录,以作技能储备. 先说段历史故事: 史前世界:1945-1994年 有一位美国科学家叫Vannevar Bush3在1945年虚构出来了一台名为Me ...
- ie浏览器下载文件中文名称乱码
//方法功能描述:判断是否是IE浏览器public boolean isMSBrowser(HttpServletRequest request) {String[] IEBrowserSignals ...
- 解决ff浏览器下载文件中文乱码问题
之前做的Word导出简历功能,前端点完要直接下载,遇到了ff浏览器下载时中文乱码的问题 function exportWord(id) {window.location.href = "/w ...
最新文章
- 阿里一面 京东一面+二面 | 掘金技术征文
- fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'
- MVC 顶层设计-HandlerMapping
- bootstrap的表单验证 vue_第45天:Web表单
- 软件测试 测试策略_测试策略| 软件工程
- python中的reduce函数用法
- mysql zip 文件安装
- EfficientDet论文阅读解析【精】公式纯手打
- Mysql锁机制简单了解一下
- 读RESTful API 设计指南心得体会
- Python-1-基础
- 分享几个有趣的Python小项目
- c++万能头文件包含的头文件
- Rhino使JavaScript应用程序更灵动
- [原创]黑产在IP攻防上的挣扎与进化
- 【腾讯位置服务】使用地点云实现企业官网中的门店地图
- protoc与protoc-gen-go安装
- mysql弱类型_PHP弱类型及相关函数Bypass
- 在IT行业中,程序员的学历重要吗?
- 视频教程-【吴刚大讲堂】Adobe Illustoator (AI)CC2019进阶与应用标准视频教程-Illustrator