java 强制关闭流报错,struts2文件下载,解决jCannot call sendError() after the response has been committed的问题...

出现这个错误的原因是当在页面点击一次下载时,向服务器发送了两次请求,所以虽然可以成功下载,但后台会报错。通过调试发现确实两次访问了download()方法,为了看的更清楚我加了调试语句错误信息如图:

Hibernate: select resource0_.id as id1_0_, resource0_.saveName as saveName2_0_, resource0_.fileName as fileName3_0_, resource0_.description as descript4_0_, resource0_.uploadTime as uploadTi5_0_ from t_resource resource0_ where resource0_.id=?

访问了一次download

访问了一次getResourceFile

访问了一次getDownloadFileName()

五月 27, 2015 9:11:24 下午 org.apache.catalina.core.StandardWrapperValve invoke

严重: Servlet.service() for servlet [default] in context with path [/blog] threw exception

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:462)

at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleErrorInDevMode(DefaultDispatcherErrorHandler.java:109)

at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleError(DefaultDispatcherErrorHandler.java:57)

at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:909)

at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:576)

at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)

at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)

at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)

at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)

at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Thread.java:745)

Hibernate: select resource0_.id as id1_0_, resource0_.saveName as saveName2_0_, resource0_.fileName as fileName3_0_, resource0_.description as descript4_0_, resource0_.uploadTime as uploadTi5_0_ from t_resource resource0_ where resource0_.id=?

访问了一次download

访问了一次getResourceFile

访问了一次getDownloadFileName()

如图所示可以清楚的看到在第一次访问下载方法成功后又访问了一次下载方法。至于为什么这样,从我的代码里我现在还没有发现原因,暂时还是觉得是struts2的一个bug吧,不然也不会有我后面的解决方案了。

解决方案有两种:

1.struts2框架+servlet api

在action中获得response,然后直接通过设置response头来输出文件流,也就是直接用servlet下载,但返回值要写成return null,这样就不交给struts2管理。 (其实这样还更方便,不过servlet的下载方式我就不讲了,主要是解决struts2的这个问题)

2.利用struts2-sunspoter-stream-1.2.jar包强制关闭socket流

如果非得要用struts2来下载(太年轻!!),可以借助struts2-sunspoter-stream-1.2.jar包来解决。

使用如下:

*下载struts2-sunspoter-stream-1.2.jar,添加到lib目录下(支持jdk1.6及以上,jdk1.6以下的版本请下载struts2-sunspoter-stream-1.0.jar)

*修改struts.xml:

在package标签下添加

将result的type="stream" 改为 type="streamx"

如下所示:

/WEB-INF/jsp/resourceMgrAction/list.jsp

resourceMgr_list

application/octet-stream;charset=ISO8859-1

resourceFile

attachment;filename=${downloadFileName}

4096

注意这里还是会两次访问下载方法,也就是还是会两次访问数据库,只是不报错而已。

修改后的后台显示如下:

Hibernate: select resource0_.id as id1_0_, resource0_.saveName as saveName2_0_, resource0_.fileName as fileName3_0_, resource0_.description as descript4_0_, resource0_.uploadTime as uploadTi5_0_ from t_resource resource0_ where resource0_.id=?

访问了一次download

访问了一次getResourceFile

访问了一次getDownloadFileName()

2015-05-27 21:36:21,591 WARN [org.apache.struts2.dispatcher.StreamResult] - StreamResultX Warn : socket write error

Hibernate: select resource0_.id as id1_0_, resource0_.saveName as saveName2_0_, resource0_.fileName as fileName3_0_, resource0_.description as descript4_0_, resource0_.uploadTime as uploadTi5_0_ from t_resource resource0_ where resource0_.id=?

访问了一次download

访问了一次getResourceFile

访问了一次getDownloadFileName()

struts2-sunspoter-stream-1.2.jar的使用可参看:http://www.oschina.net/p/streamresultx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值