Spring MVC 文件下载最佳实践
2016-02-24 16:45
423 查看
文章来源:http://sishuok.com/forum/posts/list/5351.html
不知道起这个标题是不是因为我有妄想症
坐等拍砖
私以为
在使用一个框架时,程序员分为三种级别
1.看demo开发
2.看文档开发
3.看源码开发
明显1不如2,2不如3
但是考虑时间成本3不如2,2不如1
我的原则是
有好的demo不看文档,有好的文档不看源码
对于文件下载,再简单不过了,但我比较傻,不会自己写
于是在google搜索"Spring mvc 3 download",demo版本都差不多
Java代码
@RequestMapping("download")
public void download(HttpServletResponse res) throws IOException {
OutputStream os = res.getOutputStream();
try {
res.reset();
res.setHeader("Content-Disposition", "attachment; filename=dict.txt");
res.setContentType("application/octet-stream; charset=utf-8");
os.write(FileUtils.readFileToByteArray(getDictionaryFile()));
os.flush();
} finally {
if (os != null) {
os.close();
}
}
}
因为鄙人强烈的精神洁癖,心中大骂
“这样的狗屁代码也贴在网上?”
既然使用了mvc,怎么还能暴露HttpServletResponse这样的j2ee接口出来!
我相信spring提供了更好的方式,于是开始翻阅文档,得出如下代码
Java代码
@RequestMapping("download")
public ResponseEntity<byte[]> download() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "dict.txt");
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(getDictionaryFile()),
headers, HttpStatus.CREATED);
}
理论上没问题,实现上很优雅
但是文件下载后内容如下
Java代码
"YWEJMQ0KdnYJMg0KaGgJMw=="
正确内容为
Java代码
aa 1
vv 2
hh 3
我把代码改为
Java代码
ResponseEntity<String>
输出如下
Java代码
"aa 1\n\tvv 2\n\thh 3"
相信很多人看到这已经知道了发生了什么
但是因为本人狗屎一样的基础知识,又浪费了几小时
先去看了ByteArrayHttpMessageConverter的源码
Java代码
public ByteArrayHttpMessageConverter() {
super(new MediaType("application", "octet-stream"), MediaType.ALL);
}
...
protected void writeInternal(byte[] bytes, HttpOutputMessage outputMessage) throws IOException {
FileCopyUtils.copy(bytes, outputMessage.getBody());
}
没感觉到有任何问题
捉耳挠腮了一阵子,又去看AnnotationMethodHandlerAdapter
Java代码
public AnnotationMethodHandlerAdapter() {
// no restriction of HTTP methods by default
super(false);
// See SPR-7316
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
//这里有默认值
this.messageConverters = new HttpMessageConverter[]{new ByteArrayHttpMessageConverter(), stringHttpMessageConverter,
new SourceHttpMessageConverter(), new XmlAwareFormHttpMessageConverter()};
//set时默认值全被取消了
public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
this.messageConverters = messageConverters;
再去看MappingJacksonHttpMessageConverter
Java代码
extends AbstractHttpMessageConverter<Object>//Object是万用的,就想Exception类型,优先级别应该最低
突然有一种自己是个傻 逼的感觉,浪费了大概3、4个小时
修改xml
Java代码
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
//把ByteArray加在Json前面
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name = "supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
终于如我所愿了
记录一下我这几个小时干的蠢事
顺便想说,每个例子和demo最好都以最佳实践去写
这样我这种菜鸟程序员就没机会去看源码了~
http://www.iteye.com/topic/1125784
不知道起这个标题是不是因为我有妄想症
坐等拍砖
私以为
在使用一个框架时,程序员分为三种级别
1.看demo开发
2.看文档开发
3.看源码开发
明显1不如2,2不如3
但是考虑时间成本3不如2,2不如1
我的原则是
有好的demo不看文档,有好的文档不看源码
对于文件下载,再简单不过了,但我比较傻,不会自己写
于是在google搜索"Spring mvc 3 download",demo版本都差不多
Java代码
@RequestMapping("download")
public void download(HttpServletResponse res) throws IOException {
OutputStream os = res.getOutputStream();
try {
res.reset();
res.setHeader("Content-Disposition", "attachment; filename=dict.txt");
res.setContentType("application/octet-stream; charset=utf-8");
os.write(FileUtils.readFileToByteArray(getDictionaryFile()));
os.flush();
} finally {
if (os != null) {
os.close();
}
}
}
因为鄙人强烈的精神洁癖,心中大骂
“这样的狗屁代码也贴在网上?”
既然使用了mvc,怎么还能暴露HttpServletResponse这样的j2ee接口出来!
我相信spring提供了更好的方式,于是开始翻阅文档,得出如下代码
Java代码
@RequestMapping("download")
public ResponseEntity<byte[]> download() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "dict.txt");
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(getDictionaryFile()),
headers, HttpStatus.CREATED);
}
理论上没问题,实现上很优雅
但是文件下载后内容如下
Java代码
"YWEJMQ0KdnYJMg0KaGgJMw=="
正确内容为
Java代码
aa 1
vv 2
hh 3
我把代码改为
Java代码
ResponseEntity<String>
输出如下
Java代码
"aa 1\n\tvv 2\n\thh 3"
相信很多人看到这已经知道了发生了什么
但是因为本人狗屎一样的基础知识,又浪费了几小时
先去看了ByteArrayHttpMessageConverter的源码
Java代码
public ByteArrayHttpMessageConverter() {
super(new MediaType("application", "octet-stream"), MediaType.ALL);
}
...
protected void writeInternal(byte[] bytes, HttpOutputMessage outputMessage) throws IOException {
FileCopyUtils.copy(bytes, outputMessage.getBody());
}
没感觉到有任何问题
捉耳挠腮了一阵子,又去看AnnotationMethodHandlerAdapter
Java代码
public AnnotationMethodHandlerAdapter() {
// no restriction of HTTP methods by default
super(false);
// See SPR-7316
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
//这里有默认值
this.messageConverters = new HttpMessageConverter[]{new ByteArrayHttpMessageConverter(), stringHttpMessageConverter,
new SourceHttpMessageConverter(), new XmlAwareFormHttpMessageConverter()};
//set时默认值全被取消了
public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
this.messageConverters = messageConverters;
再去看MappingJacksonHttpMessageConverter
Java代码
extends AbstractHttpMessageConverter<Object>//Object是万用的,就想Exception类型,优先级别应该最低
突然有一种自己是个傻 逼的感觉,浪费了大概3、4个小时
修改xml
Java代码
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
//把ByteArray加在Json前面
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name = "supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
终于如我所愿了
记录一下我这几个小时干的蠢事
顺便想说,每个例子和demo最好都以最佳实践去写
这样我这种菜鸟程序员就没机会去看源码了~
http://www.iteye.com/topic/1125784
相关文章推荐
- java web 开发中验证码的应用
- Eclipse中使用javap
- spring security的标签库
- Java并发学习博客
- springmvc 项目完整示例08 前台页面以及知识点总结
- JRE与JVM、JDK的区别
- springmvc 项目完整示例07 设置配置整合springmvc springmvc所需jar包springmvc web.xml文件配置
- spring-security原理学习
- 基于Struts2的供求信息网设计(一)
- springmvc 项目完整示例06 日志–log4j 参数详细解析 log4j如何配置
- ES学习(一)Windows搭建
- springmvc 项目完整示例05 日志 --log4j整合 配置 log4j属性设置 log4j 配置文件 log4j应用
- Java输入输出流
- springmvc 项目完整示例04 整合mybatis mybatis所需要的jar包 mybatis配置文件 sql语句 mybatis应用
- Java命名规则
- Struts Spring Hibernate
- springmvc 项目完整示例03 小结
- JAVA多线程
- springmvc 项目完整示例02 项目创建-eclipse创建动态web项目 配置文件 junit单元测试
- RxJava 详解