解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题
问题描述:
在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();后运行出异常但结果正确的问题的更多相关文章
- Php中文件下载功能实现超详细流程分析
浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php),该网页的代码如下 客户端从服务端下载文件的流程分析: 浏览器发送一个请求,请求访问服务器中的某个网页(如:down.php) ...
- java.lang.NoClassDefFoundError: javax/servlet/ServletOutputStream
扩展阅读:https://blog.csdn.net/kimylrong/article/details/50353161
- Java 文件下载功能 解决中文乱码
Html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...
- 手机端UC浏览器,在java开发的下载功能中存在的问题?
在java web开发中,不同浏览器对下载文件的格式有不同的要求,有时会出现视频,音频等文件无法下载的问题.我在开发中,也遇到类似的问题,觉得很苦恼. 经过百度和请教学习,得到2个解决方案. 首先得到 ...
- JAVA文件下载功能问题解决日志
今天给报告系统做了个下载功能,遇到了挺多问题,通过查资料一一解决了. 1.首先遇到的问题是:java后台的输出流输出之后,没有任何报错,浏览器端不弹出保存文件的对话框,原本是ajax请求到后台的con ...
- java web response提供文件下载功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- 解决 java.lang.ClassNotFoundException: javax.servlet.ServletContext报错
原因:tomcat找不到servlet,即缺少了servlet-api.jar包 解决方法: 我的项目是用maven搭建的 在pom.xml中加入依赖 <dependency> <g ...
- springmvc实现文件下载
springmvc实现文件下载 使用springmvc实现文件下载有两种方式,都需要设置response的Content-Disposition为attachment;filename=test2.p ...
- Maven项目红色叹号+JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java B
昨天写的关于解决JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the ...
随机推荐
- Hadoop入门进阶课程13--Chukwa介绍与安装部署
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博主为石山园,博客地址为 http://www.cnblogs.com/shishanyuan ...
- Mac常用基本命令/常用Git命令
Git地址: https://github.com/mancongiOS/command-line基本命令 目录/文件的操作 mkdir "目录名" 在当前路径下创建一个文件夹 m ...
- OpenCV开发环境配置-Windows/MinGW/Clion/CMake
临时更换成了TDM-GCC,和mingw类似,这里只是声明一下. 由于opencv下载下来的.exe安装包实际上是没有mingw(gcc)匹配的/动静态库,因此这些东西需要我们自己使用mingw编译. ...
- 图片轮播(左右切换)--JS原生和jQuery实现
图片轮播(左右切换)--js原生和jquery实现 左右切换的做法基本步骤跟 上一篇文章 淡入淡出 类似,只不过修改了一些特定的部分 (1)首先是页面的结构部分 对于我这种左右切换式 1.首先是个外 ...
- dp --- CSU 1547: Rectangle
Rectangle Problem's Link: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1547 Mean: 给你一些宽为1或2 的木 ...
- ASP.NET和MSSQL高性能分页
首先是存储过程,只取出我需要的那段数据,如果页数超过数据总数,自动返回最后一页的纪录: set ANSI_NULLS ON set QUOTED_IDENTIFIER ON GO -- ======= ...
- C#继承基本控件实现自定义控件
C#继承基本控件实现自定义控件 摘自:http://www.cnblogs.com/greatverve/archive/2012/04/25/user-control-inherit.html 自定 ...
- c#通用递归生成无限层级树
NewsType结构: Id ParentId Name children(List<NewsType>) public void LoopToAppendChildren(List< ...
- 与众不同 windows phone (50) - 8.1 新增控件: PickerFlyout, ListPickerFlyout
[源码下载] 与众不同 windows phone (50) - 8.1 新增控件: PickerFlyout, ListPickerFlyout 作者:webabcd 介绍与众不同 windows ...
- 操作AppConfig.xml中AppSettings对应值字符串
//查询AppSettings的key public static List sql() { List list = new List(); ...