解决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;
}
}
上一篇:ASP.NET网页中RAR、DOC、PDF等文件下载功能实例源代码


下一篇:PHP变量入门教程(2)超全局变量,总共9个