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



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>  


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>  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值