Spring MVC文件下载及中文文件名乱码解决
来源:互联网 发布:淘宝十大人气主播 编辑:程序博客网 时间:2024/04/28 20:36
原文地址:http://www.jianshu.com/p/58e605d881e3
内容参考 Paul Deck 著的《Spring MVC学习指南1 2版》
将文件这样的资源发送到浏览器,需要在controller中完成以下工作:
- 在请求的处理方法中使用void返回类型,并在方法中添加
HttpServletResponse
- 设置
Content-Type
, Content-Type就是常说的MIME类型,将响应的内容类型设为文件的内容类型。Content-Type
header 在某个实体的body中定义数据类型, 包含media type(媒体类型)和subtype identifiers(子类标识符)。访问http://www.iana.org/assignments/media-types 以了解更多的标准内容类型(standard content types)。如果不清楚如何设置Content-Type,要达到下载资源的效果,可以将Content-Type设置为application/octet-stream
(不区分大小写)。 - 设置一个 HTTP response header:
Content-Disposition
, 值为attachment; filename=fileName
, 这个fileName
就是下载文件后的文件名,这个文件名有可能会和这里设置fileName不一样。
上码:
方式1:读取文件作为FileInputStream
, 将内容加载到一个字节数组。随后获取HttpServletResponse的OutputStream,并调用write方法传入字节数组。
方式2:使用Java NIO's Files.copy()
方法:
Path file = Paths.get(...);Files.copy(file, response.getOutputStream());
这样代码少、而且运行得更快。
看码吧:
@Controllerpublic class DownloadController { @RequestMapping(value="/download-resource") public void downloadResource(HttpServletResponse response) { // 文件保存在/WEB_INF/data目录下 String dataDirectory = request. getServletContext().getRealPath("/WEB-INF/data"); File file = new File(dataDirectory, "sunny.pdf"); if (file.exists()) { response.setContentType("application/pdf"); response.addHeader("Content-Disposition", "attachment; filename=sunny.pdf"); byte[] buffer = new byte[1024]; FileInputStream fis = null; BufferedInputStream bis = null; // if using Java 7, use try-with-resources try { fis = new FileInputStream(file); bis = new BufferedInputStream(fis); OutputStream os = response.getOutputStream(); int i = bis.read(buffer); while (i != -1) { os.write(buffer, 0, i); i = bis.read(buffer); } } catch (IOException ex) { // do something, // probably forward to an Error page } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { } } if (fis != null) { try { fis.close(); } catch (IOException e) { } } } } } @RequestMapping(value="/download-resource1") public void downloadResource(HttpServletResponse response) { String dataDirectory = request. getServletContext().getRealPath("/WEB-INF/data"); Path file = Paths.get(dataDirectory, "sunny.pdf"); if (Files.exists(file)) { response.setContentType("application/pdf"); String fileName = "sunny.pdf"; response.addHeader("Content-Disposition", "attachment; filename=" + fileName);/*如果文件名有中文的话,进行URL编码,让中文正常显示response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));*/ try { Files.copy(file, response.getOutputStream()); } catch (IOException ex) { } } }}
针对中文文件名下载后乱码分析:
上面有说
response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
这行代码是能解决中文文件名乱码问题的,但在Safari浏览器下下载的中文文件名还是乱码的,下面提供一个解决方案,看代码:
@RequestMapping(value = "/faq") public void downloadFAQPdf(HttpServletResponse response) throws Exception { String fileName = "帮助说明.pdf";// 获取classpath下的文件 URL url = UserController.class.getClassLoader().getResource("data/" + fileName); Path file = Paths.get(url.toURI()); fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()); response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());// 解决中文文件名乱码关键行 response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"; filename*=utf-8''" + fileName); Files.copy(file, response.getOutputStream()); }
具体原因我就不细说了,参看下面这个链接(有详细的描述):
在项目中发现,使用Safari下载中文名文件的时候,下载的文件名是乱码的问题。但是这个问题在IE,Firefox,Chrome中 是没有的。原先以为是Safari的bug,但是细细研究之下你会发现这个简单的文件下载问题在HTTP协议里经历了多少波折。
研究的结果也不是我自己写的,具体可以看这两篇文章
- Serving file downloads with non-ascii
- 正确处理下载文件时HTTP头的编码问题(Content-Disposition)
这里直接贴出java代码
/*** <pre>* 浏览器下载文件时需要在服务端给出下载的文件名,当文件名是ASCII字符时没有问题* 当文件名有非ASCII字符时就有可能出现乱码** 这里的实现方式参考这篇文章* http://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/** 最终设置的response header是这样:** Content-Disposition: attachment;* filename="encoded_text";* filename*=utf-8''encoded_text** 其中encoded_text是经过RFC 3986的“百分号URL编码”规则处理过的文件名* </pre>* @param response* @param filename* @return*/public static void setFileDownloadHeader(HttpServletResponse response, String filename) { String headerValue = "attachment;"; headerValue += " filename=\"" + encodeURIComponent(filename) +"\";"; headerValue += " filename*=utf-8''" + encodeURIComponent(filename); response.setHeader("Content-Disposition", headerValue);}/*** <pre>* 符合 RFC 3986 标准的“百分号URL编码”* 在这个方法里,空格会被编码成%20,而不是+* 和浏览器的encodeURIComponent行为一致* </pre>* @param value* @return*/public static String encodeURIComponent(String value) { try { return URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; }}
阅读全文
0 0
- Spring MVC文件下载及中文文件名乱码解决
- 解决Struts2文件下载文件名中文乱码
- 下载文件 解决中文文件名乱码
- 文件下载(解决中文文件名下载乱码问题) 收集
- spring mvc 下载文件 IE浏览器文件名是乱码
- spring mvc 下载文件 IE浏览器文件名是乱码
- Struts2 .apk 文件下载及解决中文文件名乱码问题(转)
- 文件下载中文文件名乱码
- 用response对象实现文件下载,解决中文文件名乱码。
- c# web 下载文件(解决中文文件名乱码问题)
- Java实现文件下载并解决中文文件名乱码
- 打包下载文件 中文文件名乱码问题的解决
- java实现文件下载 中文文件名乱码的解决
- 下载文件默认文件名中文乱码问题的解决
- java文件下载的中文文件名乱码问题的解决
- asp.net文件下载中文文件名乱码解决
- Java实现文件下载并解决中文文件名乱码
- 解决php 文件下载 IE 文件名中文乱码
- foreach 简单使用
- windows禁用笔记本自带键盘办法
- 课程学习3
- java基础教程:常用对象之Object(20)
- 一次外场宕机引发对linux内存管理的进一步思考--Linux虚拟地址空间如何分布
- Spring MVC文件下载及中文文件名乱码解决
- UVa 12100 printer queue 解题报告
- Weibull分布(韦伯分布, 威布尔分布)函数公式, 参数,曲线分布图
- 【GDOI2018模拟7.8】质数 乱搞+哥德巴赫猜想
- (2)泛型
- linux套件安装过程中configure,make,make install的作用
- Android中关于Toast的使用体会
- MediaRecorder关于录制视频文件大小和录制时长的设置
- 汇编基础