解决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 ...
随机推荐
- iOS-修改Status Bar
一.在info.plist文件中添加一行不但要在 Status bar is initially hidden一行,选择为 YES. 二.在didFinishLaunchingWithOptions方 ...
- iOS-布局-Masonry
一.说明:demo中的举例视图介绍 UIView *_blackView; 作为父视图 UIView *_redView; 与父视图内边距为10 ...
- C++ async task
最近在搞Android 开发,里面多线程的使用比较频繁,java多线程接口很方便. Thread, AysncTask, Handler 这些接口比起posix提供的pthread_create()等 ...
- ASP.NET 让无码编程不在是梦 -.NET通用平台、通用权限、易扩展、多语言、多平台架构框架
先拿出我半前年前平台的设计初稿,经过半年的努力我已经完成了该设计稿的所有功能.并且理念已经远远超出该设计稿. 下面是一些博友对我贴子的评价: 1.楼主,想法很美好,现实很骨感,我们公司就有一套你说的这 ...
- 【分享】iOS功能界面漂亮的弹出框
STPopup 为 iPhone 和 iPad提供了 STPopupController UINavigationController 弹出的风格. 特性: Extend your view cont ...
- python反转字符串(简单方法)及简单的文件操作示例
Python反转字符串的最简单方法是用切片: >>> a=' >>> print a[::-1] 654321 切片介绍:切片操作符中的第一个数(冒号之前)表示切片 ...
- Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现
在一般的权限系统里面,可能经常会看到系统的黑名单或者白名单的拦截功能.在一般权限系统里面,常见的黑名单就是禁止用户在某些IP上登录系统,白名单就是允许用户只在某些IP上登录系统.本随笔主要介绍在我的权 ...
- 利用mciSendString播放音频
最近在写音频播放器,不过有点懒散,开发进度很慢,一天只做了一点点东西.其实就是让程序能播放音频.这个在我大二学winform程序开发时书上有说,那是书上教的是用media player的COM组件,而 ...
- 【循序渐进学Python】8.面向对象的核心——类型(下)
1 构造和初始化对象 __init__方法是Python内建众多魔法方法(什么是魔法方法?)中最常见的一个,通过这个方法我们可以定义一个对象的初始操作.当构造函数被调用的时候的任何参数都会传递给__i ...
- MSIL指令集
名称 说明 Add 将两个值相加并将结果推送到计算堆栈上. Add.Ovf 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上. Add.Ovf.Un 将两个无符号整数值相加,执行溢出检查,并且 ...