报错:java.lang.IllegalStateException: getOutputStream() has already been called for this response


错误信息详情:

严重: 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

分析

翻阅了挺多资料,最后总结如下:

  1. 其实就是因为 JSP 中同时用了 response.getOutputStream() 以及 JSP 内置对象 out.write().
  2. Serlvet 规范中不能同时使用这两个。只能选其中一个。所以再来分析代码:
    1. response.getOutputStream() : 很明显在代码中已经用到了。
    2. 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;
%>


喜欢就来点个赞吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Charlven

你的鼓励将是我最大的动力哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值