错误信息详情:
严重: Servlet.service() for servlet [jsp] in context with path [/exportExcel] threw exception [java.lang.IllegalStateException: getOutputStream() has already been called for this response] with root cause
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:678)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:213)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:194)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:126)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
at org.apache.jsp.export_jsp._jspService(export_jsp.java:566)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
...
问题背景
在写一个 download.jsp ,提供下载文件功能(部分关键代码)如下:
....
<%
...
response.addHeader("Content-Disposition","attachment;filename=\"..\"");
response.addHeader("Content-Length",43408);
...
OutputStream out = response.getOutputStream();
InputStream in;
//todo intialize inputStream
...
while((n = in.read(b)) != -1) {
out.write(b, 0, n);
}
out.flush;
%>
运行结果:
结果功能 -> 正常,但是有一点不爽!!日志一直有报错,报错如下:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
分析
翻阅了挺多资料,最后总结如下:
- 其实就是因为 JSP 中同时用了 response.getOutputStream() 以及 JSP 内置对象 out.write().
- Serlvet 规范中不能同时使用这两个。只能选其中一个。所以再来分析代码:
response.getOutputStream()
: 很明显在代码中已经用到了。out.write()
:这个很有可能是 JSP 中存在空行或者回车导致的。至于到底是什么时候有 out.write() 。大家可以到 tomcat 目录下看看 jsp 生成的 .java 文件就一目了然了。
解决方案
参考网上的,在调用 response.getOutStream() 之前清空一下两者的缓存。同时更新 out 的内容。
详情看代码(实践已证明可行)↓
<%
// 同时 reset response 和 清空 out
response.reset();
out.clear();
out = pageContext.pushBody();
// ---------------------增加上面的内容--------------------------------------
...
response.addHeader("Content-Disposition","attachment;filename=\"..\"");
response.addHeader("Content-Length",43408);
...
OutputStream out = response.getOutputStream();
InputStream in;
//todo intialize inputStream
...
while((n = in.read(b)) != -1) {
out.write(b, 0, n);
}
out.flush;
%>
喜欢就来点个赞吧~