问题描述:

  在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. Appium移动自动化测试(三)--安装Android模拟器

    当Android SDK安装完成之后,并不意味着已经装好了安装模拟器.Android系统有多个版本,所以我们需要选择一个版本进行安装. 第三节  安装Android 模拟器 我这里以Android 4 ...

  2. 美了美了!22款精美的 iOS 应用程序图标模板

    22款制作精美的 iOS 应用程序图标设计作品,遵循图形设计的现代潮流,所有图标都非常了不起,给人惊喜.通过学习这些移动应用程序图标,设计人员可以提高他们的创作,使移动用户界面看起来更有趣和吸引人. ...

  3. 基于Redis的BloomFilter算法去重

    BloomFilter算法及其适用场景 BloomFilter是利用类似位图或者位集合数据结构来存储数据,利用位数组来简洁的表示一个集合,并且能够快速的判断一个元素是不是已经存在于这个集合.因为基于H ...

  4. 链表中倒数第k个结点

    题目: 输入一个链表,输出该链表中倒数第k个结点. 思路: 因为是单向链表,如果使用最普通的遍历来解决的话会多出很多不必要的遍历.有一个比较好的解法,设置两个指针两个指针之间差k-1个位置,也就是当后 ...

  5. eclipse中去掉Js/javsscript报错信息

    1.首先在problem>errors中删除所有js错误: 如下图 2.然后再勾选掉javascript Validator: 3.clean下项目吧,你会发现再也不出现js红叉叉了,哈哈.

  6. 控制网页的Panel是否显示

    在网页上有十二个Panel控件,默认状态是不显示的,根据当前月作为条件去控制对应的Panel控件显示. Insus.NET以下使用三种方法来实现它,先是第一种,使用FindControl方法 第二种方 ...

  7. Java开发中的23种设计模式(转)

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  8. display:inline-block兼容ie6/7的写法

    2.display:inline-block作用? 使用display:inline-block属性,可以使行内元素或块元素能够变成行内块元素,简单直白点讲就是不加float属性就可以定义自身的宽.高 ...

  9. EF工作中踩过的坑.

    1.EF同一个linq里边不支持两个或两个以上不同dbcontext的使用,必须拆解开才能使用; ef也不支持自定义集合和dbcontext属性的混合使用. 2.如果要用用统一域账号连接databas ...

  10. java四大域总结

    最近学完了web部分,发现有些地方总是单个容易理解,可是把所有的放在一起来大杂烩,总是有那么几个知识点容易混淆.其实网上的资料已经够多了,虽然也不乏辛劳的搬运工.可是最终的目的不就是要我们自身理解吗? ...