问题描述
在调用BufferedOutputStream的flush方法时报了如下的错,没明白这是报的什么错:java.io.IOException: write beyond end of streamat java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:102)at java.util.zip.GZIPOutputStream.write(GZIPOutputStream.java:72)at com.bstek.dorado.core.GZIPEncodeFilter$GZIPServletStream.write(GZIPEncodeFilter.java:130)at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)at com.fenet.insurance.mm.invoice.action.InvoiceInfoToXMLAction.invoiceExport(InvoiceInfoToXMLAction.java:115)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at com.bstek.dorado.view.ViewModelSupport.handleUpdate(ViewModelSupport.java:954)at com.bstek.dorado.view.rpc.UpdateDataRPCHandler.internalExecute(UpdateDataRPCHandler.java:119)at com.bstek.dorado.view.rpc.AbstractRPCHandler.execute(AbstractRPCHandler.java:119)at com.bstek.dorado.view.smartweb.v2.ViewServiceController.doRPC(ViewServiceController.java:457)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at com.bstek.dorado.action.Controller.doDispatch(Controller.java:220)at com.bstek.dorado.action.Controller.internalDispatch(Controller.java:174)at com.bstek.dorado.action.Controller.internalDispatch(Controller.java:138)at com.bstek.dorado.action.Controller.invokeAction(Controller.java:113)at com.bstek.dorado.action.ActionHandler.invokeAction(ActionHandler.java:140)at com.bstek.dorado.action.ActionHandler.invokeAction(ActionHandler.java:130)at com.bstek.dorado.core.DoradoServlet.doGet(DoradoServlet.java:85)at com.bstek.dorado.core.DoradoServlet.doPost(DoradoServlet.java:109)at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)at com.bstek.dorado.core.FilterHandle.internalDoFilter(FilterHandle.java:362)at com.bstek.dorado.core.FilterHandle.doAgentRPCFilter(FilterHandle.java:309)at com.bstek.dorado.core.FilterHandle.doFilter(FilterHandle.java:155)at com.bstek.dorado.core.DoradoFilter.doFilter(DoradoFilter.java:72)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)at java.lang.Thread.run(Thread.java:662)代码也贴出来吧,还请大家帮忙分析下,这个问题出在哪里:public void invoiceExport(ParameterSet parameters,ParameterSet outParameters) throws Exception {String xml = "ddddddddd";HttpServletResponse response = ContextManager.response;String fileName = "file.xml";response.reset();// 必须加,不然保存不了临时文件response.setContentType("application/x-msdownload");// 设置文件内容格式,防止浏览器自动打开BufferedOutputStream bos=null;try {// 设置文件名编码格式fileName = java.net.URLEncoder.encode(fileName, "GB2312");} catch (UnsupportedEncodingException e) {throw new RuntimeException("不支持的编码格式!!!");}// 设置下载的文件名response.addHeader("content-Disposition", "attachment;filename=" + fileName);try {// 复制流bos=new BufferedOutputStream(response.getOutputStream());bos.write(xml.getBytes());} catch (FileNotFoundException e) {e.printStackTrace();throw new RuntimeException("找不到文件!!!");} catch (IOException e) {e.printStackTrace();throw new RuntimeException("写文件错误!!!");} finally {bos.flush();bos.close();}}
解决方案
应该是你在调这个方法之前,已经有人写过一次response.getOutputStream()并关闭了而你调的reset方法没有很好的还原回response的状态,导致你再写时候这个流还是关闭的,所以报错会在flush时候发生,如果你没加bufferedoutputstream,那么就是直接在write时候发生了你可以试着在web.xml去掉com.bstek.dorado.core.GZIPEncodeFilter这个filter看看,应该可以解决这个问题如果这个是公司框架,要么找人修复这个reset的问题或者你找个更早一点的时机调你这个方法
解决方案二:
close 就会调用flush 好吧你自己用个 buffer,一部分一部分的flush呗
解决方案三:
目测是这里出现问题:bos=new BufferedOutputStream(response.getOutputStream()); bos.write(xml.getBytes()); 因为:write beyond end of streambos是写流到目标,而xml.getBytes()这个长度很短,只有"dddddd"的长度。如果把它改成这样bos=new BufferedOutputStream(response.getOutputStream()); bos.write(new byte[1000000]); 这个byte要足够大,但不能大于内存大小,1000000肯定够了,如果没报错就上面猜测成立。
解决方案四:
try {// 复制流bos=new BufferedOutputStream(response.getOutputStream());bos.write(xml.getBytes());} catch (FileNotFoundException e) {e.printStackTrace();throw new RuntimeException("找不到文件!!!");} catch (IOException e) {e.printStackTrace();throw new RuntimeException("写文件错误!!!");} finally {bos.flush();bos.close();}} 改成如下试试try {// 复制流bos=new BufferedOutputStream(response.getOutputStream());bos.write(xml.getBytes());bos.flush();} catch (FileNotFoundException e) {e.printStackTrace();throw new RuntimeException("找不到文件!!!");} catch (IOException e) {e.printStackTrace();throw new RuntimeException("写文件错误!!!");} finally {if (bos != null)bos.close();}}