Spring MVC 文件下载过程中 出现下载文件乱码

Spring MVC 中文件上传与下载功能实现 假设你是一个幼儿园老师,需要让小朋友们把自己的画传到班级系统,再分享给其他小朋友。这个过程其实就是文件上传(小朋友把画"传"给系统)和文件下载(其他小朋友把画"取"走)。电商平台:商家上传商品图片;社交应用:用户上传头像、朋友圈视频;企业系统:员工上传报销凭证、下载工资条。Spring MVC作为Java Web开发的主流框架,提供了简洁、高效的文件处理方案。理解文件上传下载的底层原理(Multipart请求是什么?掌握Spring MVC中文件上传的配置与代码实现; 阅读详情

在使用一个框架时,程序员分为三种级别 
1.看demo开发 
2.看文档开发 
3.看源码开发 

明显1不如2,2不如3 
但是考虑时间成本3不如2,2不如1 

我的原则是 
有好的demo不看文档,有好的文档不看源码 

对于文件下载,再简单不过了,但我比较傻,不会自己写 
于是在google搜索"Spring mvc 3 download",demo版本都差不多 

Java代码     收藏代码
  1. @RequestMapping("download")  
  2. public void download(HttpServletResponse res) throws IOException {  
  3.     OutputStream os = res.getOutputStream();  
  4.     try {  
  5.         res.reset();  
  6.         res.setHeader("Content-Disposition", "attachment; filename=dict.txt");  
  7.         res.setContentType("application/octet-stream; charset=utf-8");  
  8.         os.write(FileUtils.readFileToByteArray(getDictionaryFile()));  
  9.         os.flush();  
  10.     } finally {  
  11.         if (os != null) {  
  12.             os.close();  
  13.         }  
  14.     }  
  15. }  



因为鄙人强烈的精神洁癖,心中大骂 
“这样的狗屁代码也贴在网上?” 

既然使用了mvc,怎么还能暴露HttpServletResponse这样的j2ee接口出来! 

我相信spring提供了更好的方式,于是开始翻阅文档,得出如下代码 

Java代码     收藏代码
  1. @RequestMapping("download")  
  2. public ResponseEntity<byte[]> download() throws IOException {  
  3.     HttpHeaders headers = new HttpHeaders();  
  4.     headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);  
  5.     headers.setContentDispositionFormData("attachment", "dict.txt");  
  6.     return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(getDictionaryFile()),  
  7.                                       headers, HttpStatus.CREATED);  
  8. }  



理论上没问题,实现上很优雅 
但是文件下载后内容如下 

Java代码     收藏代码
  1. "YWEJMQ0KdnYJMg0KaGgJMw=="  



正确内容为 

Java代码     收藏代码
  1. aa  1  
  2. vv  2  
  3. hh  3  



我把代码改为 

Java代码     收藏代码
  1. ResponseEntity<String>  



输出如下 

Java代码     收藏代码
  1. "aa    1\n\tvv     2\n\thh  3"  



相信很多人看到这已经知道了发生了什么 
但是因为本人狗屎一样的基础知识,又浪费了几小时 

先去看了ByteArrayHttpMessageConverter的源码 

Java代码     收藏代码
  1.        public ByteArrayHttpMessageConverter() {  
  2.     super(new MediaType("application", "octet-stream"), MediaType.ALL);  
  3. }  
  4.        ...  
  5.        protected void writeInternal(byte[] bytes, HttpOutputMessage outputMessage) throws IOException {  
  6.     FileCopyUtils.copy(bytes, outputMessage.getBody());  
  7. }  


没感觉到有任何问题 

捉耳挠腮了一阵子,又去看AnnotationMethodHandlerAdapter 

Java代码     收藏代码
  1.       public AnnotationMethodHandlerAdapter() {  
  2. // no restriction of HTTP methods by default  
  3. super(false);  
  4.   
  5. // See SPR-7316  
  6. StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();  
  7. stringHttpMessageConverter.setWriteAcceptCharset(false);  
  8. //这里有默认值  
  9.               this.messageConverters = new HttpMessageConverter[]{new ByteArrayHttpMessageConverter(), stringHttpMessageConverter,  
  10.         new SourceHttpMessageConverter(), new XmlAwareFormHttpMessageConverter()};  
  11.   
  12.         
  13.       //set时默认值全被取消了  
  14.       public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {  
  15. this.messageConverters = messageConverters;  



再去看MappingJacksonHttpMessageConverter 

Java代码     收藏代码
  1. extends AbstractHttpMessageConverter<Object>//Object是万用的,就想Exception类型,优先级别应该最低  



突然有一种自己是个傻 逼的感觉,浪费了大概3、4个小时 

修改xml 

Java代码     收藏代码
  1. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
  2.     <property name="messageConverters">  
  3.         <list>  
  4.             //把ByteArray加在Json前面  
  5.             <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>  
  6.             <bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >  
  7.                 <property name = "supportedMediaTypes">  
  8.                     <list>  
  9.                         <value>text/plain;charset=UTF-8</value>  
  10.                     </list>  
  11.                 </property>  
  12.             </bean>  
  13.         </list>  
  14.     </property>  
  15. </bean>  



终于如我所愿了 

记录一下我这几个小时干的蠢事 
顺便想说,每个例子和demo最好都以最佳实践去写 
这样我这种菜鸟程序员就没机会去看源码了~ 

 

http://www.iteye.com/topic/1125784

CKAD-CN 考试知识点分享(2) CronJob 成功创建 CronJobppi,每 5 分钟执行一次计算任务;配置了和;设置,超时自动终止;确保 Pod 不重启;手动创建ppi-testJob 验证功能正常;所有任务要求均已满足。 阅读详情

相关推荐

避坑指南:STM32CubeMX安装后,你的第一个工程为什么中文全是乱码?

本文详细解析了STM32CubeMX安装后中文乱码问题的根源及解决方案。从诊断乱码现象到分析编码冲突背景,提供了新项目UTF-8化、旧项目GBK兼容及版本降级等多种实用方案,帮助开发者彻底解决这一常见问题。

weixin_30699955的博客 474

Spring MVC 文件下载最佳实践

文章来源:http://sishuok.com/forum/posts/list/5351.html 不知道起这个标题是不是因为我有妄想症  坐等拍砖  私以为  在使用一个框架时,程序员分为三种级别  1.看demo开发  2.看文档开发  3.看源码开发  明显1不如2,2不如3  但是考虑时间成本3不如2,2不如1  我的原则是  有好的de

Thinking 7419

如何制作微信小程序的在线购物商城应用

首先,你需要规划好商城的整体框架,确定好你的目标用户群体,思考他们的需求是什么。接下来,使用微信开发者工具创建一个新的小程序项目,输入你的AppID,选择好保存路径,点击“创建”,一个新的商城雏形就诞生了。你可以把这里当作自己的家,无论是工作之余的小憩,还是寻找灵感的驿站,我都希望你能在这里找到属于你的那份快乐和满足。数据是现代商业的灵魂,通过数据分析,你可以更准确地把握用户的行为模式,从而做出更明智的决策。

master_chenchen的博客 2427

Spring MVC之ResposeEntity下载文件

Spring Mvc中用ResponseEntity方式下载文件如下: @RequestMapping("/download") public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("fileName") String fileNam...

weixin_33832340的博客 217

TYPE-C接口电路设计篇(一)

常见USB接口类型 随着USB Type-C接口的推行,USB Type-C是一种通用串行总线(USB)的硬件接口形式,USB Type-C接口在消费类产品普及程度越来越高,常见的适配器、笔电、手机等产品都兼容USB Type-C设计,接口多元化逐渐趋向归一,从而可以看出USB Type-C的重要性。 在了解USB Type-C接口之前,我们先来回顾下USB Type-A和USB Type-B接口,USB3.0 Type-A和Type-B接口定义分别如下。 USB 3.0...

JWu的博客 3万+

Arduino——GY39大气压、温湿度、光照模块

前几天买东西的时候买了一个GY39,这个模块集成了温湿度,大气压,海拔,光照一体,使用起来很方面。它有两种工作模式使用串口模式时需要搭配转接板,我选择了IIC模式,看一下通信协议吧,就是关于高八位和低八位的数据。看一下接线。

戚晨夕的博客 2604

文件下载实现

后台: /** * 下载文件 * @param request * @return * @throws IOException */ @RequestMapping("/download") public ResponseEntity downloadFile(HttpServletRequest request) throws IOException { if(r

yangwen123222的博客 464

OpenClaw人人养虾:接入Matrix

Matrix 是一个开放的去中心化通讯协议(Decentralized Communication Protocol),任何人都可以搭建自己的 Homeserver(家服务器)并与全球 Matrix 网络互联。OpenClaw 通过 Matrix Client-Server API 实现接入。

王国平的博客 526

AngularJs接受 ResponseEntity<byte[]>二进制流,实现下载文件

后台使用SpringMVC 的 ResponseEntity 参数返回类型,前台使用AngularJs请求。代码如下 后台代码: @RequestMapping("/down") @ResponseBody public ResponseEntity expoertExcel(..) throws IOException{      ...         return new Resp

wspc_的博客 5981

同步调相机启动与并网控制技术方案

同步调相机起动与并网控制技术方案采用背靠背变流器系统,通过静止变频器(SFC)策略实现无原动机驱动的同步电机从静止到同步转速的平稳起动。方案详细阐述了硬件自检、模块初始化、转子位置检测等关键环节,重点解决启动转矩为零、冲击电流大等挑战。系统基于STM32或C2000系列控制器,包含网侧/机侧变流器、检测保护单元及通信接口,通过励磁脉冲和电压响应分析实现高精度转子初始定位,为后续并网提供必要条件。代码级实现涵盖了ADC自检、数字IO验证及通信端口测试等核心功能。

huanghm88的专栏 305

生成自定义工具栏

我们生成了和VBA时代几乎一样的常用的工具栏。用WPF也可以完成以后的插件开发,界面控件编写基本靠自己绘画,还有用代码去控制,代码结构像HTML,做过网站的应该可以很快入手。其它后台C#代码除了对控件代码的控制外,和WinForm基本相同,但目前来看用WPF是生成自定义工具栏的较好的办法。当然,你也可以在工具栏命令中调用WinForm程序,对Coreldraw进行操作,这也应该是比较高效的办法,下次会讨论。资源的加入是本次调试的难点之一,我们的目标是让图片资源嵌入到程序中去,不必去电脑文件目录去调用;

力先生C#程序开发 1374

springboot 返回二进制文件流

@GetMapping("/getTemplateFile") @ApiOperation("数据模板下载") public ResponseEntity<byte[]> downFile(HttpServletRequest request) throws IOException { File file = new File("C/AA"); filename = getFilename(request, filename); ...

小叶lr的博客 9929

Spark Sql 连接mysql

转载请务必注明原创地址为:http://dongkelun.com/2018/03/21/sparkMysql/ 1、基本概念和用法(摘自spark官方文档中文版) Spark SQL 还有一个能够使用 JDBC 从其他数据库读取数据的数据源。当使用 JDBC 访问其它数据库时,应该首选 JdbcRDD。这是因为结果是以数据框(DataFrame)返回的,且这样 Spark SQL操作轻松或便......

主要分享大数据相关的知识,如Spark、Hudi 1万+

解决Spring文件下载时文件损毁问题

spring文件下载、文件损坏解决方法

昔年_惜年的博客 4425

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java Web文件下载1——文件下载实现和乱码处理

Java文件下载/Springmvc文件下载的实现以及需要注意的一些细节问题,完美解决各浏览器的中文文件名乱码问题。欢迎大家讨论交流。

sheen口开河 6051

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

javaEE项目Multipartfile实现文件上传下载并解决上传与下载文件中文乱码的问题

里面包含了文件上传下载并解决上传与下载文件中文乱码的问题,运用正则表达式判断字符串中是否包含中文和得到一个文件夹下的所有文件的方法,几乎集合了上传下载所需要的所有东西.下面代码加红的部分就是这几个重要点! 知识要大家一起分享嘛. 首先,需要配置好Spring+Springmvc的环境 1.在maven中添加: 如果你不是用maven管理项目的话,就百度Multipartfile所需的jar包...

Tech Station 7854

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

JAVA文件下载

@RequestMapping("/fileDownLoad.html") public ResponseEntity<byte[]> fileDownLoad(HttpServletRequest request) throws Exception{ ServletContext servletContext = request.getSession()...

qq_38949960的博客 307

spring mvc开发过程知识点记录

给一个客户做的一个小项目,需求就是输入类似一个短网址http://dd.yy/xxxx然后跳转到另外一个域名下的图书文件。(实际很多短网址站都提供API供调用吧,不过客户需求是他自己建立一个短网址服务然后跳转到服务器上另外一个网站下载相应图书) 以前没单独用spring开发的经验,实际用java的经验也比较少,所以记录下开发过程中遇到的问题以及有价值的知识点记录下供自己和后来者备忘吧。有些地方理...

weixin_30951389的博客 66

SpringMVC实现文件上传下载

/* * 保存及更新数据 */ @RequestMapping(value = "/save", method = RequestMethod.POST) public String save(Model model, Check check, MultipartFile file) throws IllegalStateException, IOExceptio

Radom&7 322

SpringMVC中web.xml的常用配置文件

<!-- 请求method支持 put 和 delete 必须添加该过滤器 作用:可以过滤所有请求,并可以分为四种 使用该过滤器需要在前端页面加隐藏表单域 <input type="hidden" name="_method" value="请求方式(put/delete)"> post会寻找_method中的请求式是不是put 或者 delete,如果不是

biao285869350 1583

SpringMVC框架学习总结

文件上传和下载步骤1.导入文件上传的相关jar包. 2.在application.xml中配置文件上传解析器. 3.编写核心类. 开发过程中遇到的问题及原因说明需要配置文件上传解析器. 缺少文件上传的包 源码解析HanderMapping 请求映射处理器:(说明书)作用:根据不同的请求选择最合适的处理器(自己编写的控制器),请求映射处理器可以配置多个,谁最先匹配就执行谁。 [org.springfr

姝涵的一年365 536

SpringMVC

假设:你的项目的架构,是设计好的?还是演进的? All in one---->微服务 演进的,

Little___Turtle的博客 251

SpringMVC完整学习

注重学习SpringMVC的执行流程,面试必问!

llx522的博客 860

Spring MVC中的文件下载

Spring MVC中的文件下载

GuessHat的博客 328

文件下载内容乱码

最近整理代码的时候发现了一个以前从没遇到过的问题:在 Spring MVC 4.3.10.RELEASE 框架下编写文件下载功能时,下载下来的文件出现了内容乱码的情况(其实也不是乱码,内容实际上是字节数组转换的成的字符串),而且不管中英文,都有问题。而文件名却不管中英文都没问题。于是便开始查找问题的所在。幸运的是没过多久便找到了的“犯罪嫌人”,以下是案件记录。 受害人代表 测试.txt(案发前...

Supreme_Sir的博客 5191

利用 spring mvc ResponseEntity 做文件下载

controller代码: @RequestMapping(value = "/cmpSts/{cmpId}", method = RequestMethod.GET) public ResponseEntity cmpSts(@PathVariable int cmpId, HttpServletRequest request, HttpServletResponse resp

taotoxht的专栏 1万+
上一篇: 如何在CentOS 7上修改主机名
下一篇: 将jar 作为linux服务程序运行的方法.
kernel_32
博客等级 码龄22年 23粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值