问题描述:

  在springmvc中实现文件下载功能一般都会使用javax.servlet.ServletOutputStream out = response.getOutputStream();封装下载的工具类,稍后我会分享该工具类。

当使用了response.getOutputStream()后,由于在同一个请求中JSP或Servlet中同时调用了Response的getWriter和getOutputStream就会抛此异常,异常部分代码如下:

严重: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:)
at org.apache.jsp.download_jsp._jspService(download_jsp.java:)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:)

网上有的解决办法都是基于jsp中有java代码的,但是如果想在springmvc的controller中使用时难免不太对应,经过我的摸索,由于下载文件大多数情况况下都是留在原页面,那么我试了一下将返回值设为void,结果巧妙解决了以上问题,特以此记录。

测试的下载工具类如下:;


import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class DownloadFile {
/**
* 下载文件,file 为文件位置
*/
public static void downloadFile(String file, HttpServletRequest request,
HttpServletResponse response) {
try {
File tempFile = new File(file.trim());
String fileName = tempFile.getName();
InputStream is = new FileInputStream(file);
response.reset(); // 必要地清除response中的缓存信息
request.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-disposition",
"attachment;" + UserAgentUtil.encodeFileName(request, fileName));
//response.setHeader("Content-Length", String.valueOf(fileLength));
/*response.setHeader("Content-Disposition", "attachment; filename="
+ java.net.URLEncoder.encode(fileName, "UTF-8"));*/
javax.servlet.ServletOutputStream out = response.getOutputStream();
byte[] content = new byte[1024];
int length = 0;
while ((length = is.read(content)) != -1) {
out.write(content, 0, length);
}
out.flush();
out.close();
       is.close();
} catch (Exception e) {
e.printStackTrace();
}
} }

测试的controller层代码如下:

@RequestMapping(value = "/download.do")
public void downloadDetailPrice(//@RequestParam String id,
HttpServletRequest request, HttpServletResponse response) {
String file = "D:\\a.txt";
DownloadFile.downloadFile(file,request,response); }

浏览器客户端防乱码工具类:

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import javax.mail.internet.MimeUtility;
import javax.servlet.http.HttpServletRequest; /** @author pangchao E-mail: pangchao620@163.com
* @date : 2016年2月24日 上午11:27:26
* @Description : 文件下载时浏览器端防乱码编码工具类
* @version 1.0
*/
public class UserAgentUtil { public static String encodeFileName(HttpServletRequest request, String fileName) {
String userAgent = request.getHeader("User-Agent");
String rtn = "";
try {
String new_filename = URLEncoder.encode(fileName, "UTF8");
// 如果没有UA,则默认使用IE的方式进行编码,因为毕竟IE还是占多数的
rtn = "filename=\"" + new_filename + "\"";
if (userAgent != null) {
userAgent = userAgent.toLowerCase();
// IE浏览器,只能采用URLEncoder编码
if (userAgent.indexOf("msie") != -1) {
rtn = "filename=\"" + new_filename + "\"";
}
// Opera浏览器只能采用filename*
else if (userAgent.indexOf("opera") != -1) {
rtn = "filename*=UTF-8''" + new_filename;
}
// Safari浏览器,只能采用ISO编码的中文输出
else if (userAgent.indexOf("safari") != -1) {
rtn = "filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"";
}
// Chrome浏览器,只能采用MimeUtility编码或ISO编码的中文输出
else if (userAgent.indexOf("applewebkit") != -1) {
new_filename = MimeUtility.encodeText(fileName, "UTF8", "B");
rtn = "filename=\"" + new_filename + "\"";
}
// FireFox浏览器,可以使用MimeUtility或filename*或ISO编码的中文输出
else if (userAgent.indexOf("mozilla") != -1) {
rtn = "filename*=UTF-8''" + new_filename;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return rtn;
}
}

解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题的更多相关文章

  1. Php中文件下载功能实现超详细流程分析

    浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php),该网页的代码如下   客户端从服务端下载文件的流程分析: 浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php) ...

  2. java.lang.NoClassDefFoundError: javax/servlet/ServletOutputStream

    扩展阅读:https://blog.csdn.net/kimylrong/article/details/50353161

  3. Java 文件下载功能 解决中文乱码

    Html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  4. 手机端UC浏览器,在java开发的下载功能中存在的问题?

    在java web开发中,不同浏览器对下载文件的格式有不同的要求,有时会出现视频,音频等文件无法下载的问题.我在开发中,也遇到类似的问题,觉得很苦恼. 经过百度和请教学习,得到2个解决方案. 首先得到 ...

  5. JAVA文件下载功能问题解决日志

    今天给报告系统做了个下载功能,遇到了挺多问题,通过查资料一一解决了. 1.首先遇到的问题是:java后台的输出流输出之后,没有任何报错,浏览器端不弹出保存文件的对话框,原本是ajax请求到后台的con ...

  6. java web response提供文件下载功能

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  7. 解决 java.lang.ClassNotFoundException: javax.servlet.ServletContext报错

    原因:tomcat找不到servlet,即缺少了servlet-api.jar包 解决方法: 我的项目是用maven搭建的 在pom.xml中加入依赖 <dependency> <g ...

  8. springmvc实现文件下载

    springmvc实现文件下载 使用springmvc实现文件下载有两种方式,都需要设置response的Content-Disposition为attachment;filename=test2.p ...

  9. Maven项目红色叹号+JavaWeb: 报错信息The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java B

    昨天写的关于解决JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the ...

随机推荐

  1. gulp-uglify《JS压缩》----gulp系列(四)

    本节实现JS压缩,在实现压缩前,先配置JS任务,设置源目录和输出目录. 在系列(三)代码的基础上,再进行扩展. 1.找到gulp->config.js,对JS进行源目录(src->img) ...

  2. Linux - 常用Shell快捷键

    Common Shortcut Key 用途 快捷键 说明 光标移动 Ctrl + a 把光标移到行首 Ctrl + e 把光标移到行尾 Ctrl + x 在 EOL 和当前位置移动光标 输入编辑 C ...

  3. 论python中的作用域

    编程语言从早至今,可以分为面向过程编程.面向函数编程和面向对象编程.BASIC语言是典型的面向过程编程的语言,C语言支持面向函数编程,但不支持面向对象,JAVA只支持面向对象编程,python同时支持 ...

  4. SQL Server 诊断查询-(4)

    Query #41 Memory Clerk Usage -- Memory Clerk Usage for instance -- Look for high value for CACHESTOR ...

  5. 组合数(Lucas定理) + 快速幂 --- HDU 5226 Tom and matrix

    Tom and matrix Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5226 Mean: 题意很简单,略. analy ...

  6. Titanium开发环境搭建第一个坑

    操作系统: Ubuntu 12.04 LTS AMD64 在Titanium Studio中,装Titanium CLI怎么都不能成功,到了一个进度,发现卡在那里,硬盘一直狂闪,发现在Studio的文 ...

  7. 数据库==>>数据查询基础

    数据查询基础 还好吗?几天不见,甚是思念呀!笑对人生,好好生活,快快乐乐的迎接我们的美好未来吧! 好吧!抒情结束,我们一起来学习一下我们今天的主题:数据查询基础,很有意思哟.让我们来感受它的魅力吧! ...

  8. 安装性能测试工具:sysbench和使用apache的ab

    一.软件的用途,它主要包括以下几种方式的测试:1.cpu性能2.磁盘io性能3.调度程序性能4.内存分配及传输速度5.POSIX线程性能6.数据库性能(OLTP基准测试) 这个软件为什么找不到官网呢? ...

  9. Python迭代器:捕获Generator的返回值

    但是用for循环调用generator时,发现拿不到generator的return语句的返回值.如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的v ...

  10. c#泛型方法返回null的问题

    c#的泛型方法实现和java实现有点不同,在java中,所有的泛型方法运行时类型必须是引用类型,所以和非泛型一样可以返回null. 但是c#中有点不同,可以同时是值类型和引用类型,而值类型不能赋值nu ...