JSP下载打包文件及java.lang.IllegalStateException异常解决

     项目需求的缘故,需要把备份数据库表的文件及生成的SQL脚本打包下载(本想做成可以浏览目录的方式,不得,故采用该种方法),从网上找了点资料:下载采用了
    org.apache.tools.zip.*;(
使用时把ant.jar放到classpath中,程序中使用import org.apache.tools.zip.*; 
Apache Ant 下载地址:[url]http://ant.apache.org/[/url] 
),因JDK本身的java.util.zip有中文乱码问题;
代码如下:
   <%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="org.apache.commons.lang.*" %>
<%@page import="com.cupdata.util.*" %>
<%@page import="org.apache.tools.zip.*" %>
<%
//读取文件集合
ArrayList<File>  files = FileUtil.getFiles(savePath);//传入保存文件的路径savePath,并读取文件集合,代码就不写了,呵呵

//设置浏览器显示的内容类型为Zip  
      response.setContentType("application/zip");  
      //设置内容作为附件下载,并且名字为:export.zip  
      response.setHeader("Content-Disposition", "attachment; filename= export.zip");  
        
      //装饰输出流为Zip输出流  
      ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());          
     
        
      //读取文件的缓存  
      byte[] buffer = new byte[1024];  
      int length = 0;  
        
      for (File file:files) { 
            
          //向Zip中添加一个条目(也就是添加一个文件)  
          zos.putNextEntry(new ZipEntry(file.getPath()));  
            
          //读取文件数据写到ZipOutputStream  
          BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));  
          while((length = bis.read(buffer))!=-1){  
              zos.write(buffer);  
          }  
            
          //关闭zip条目  
          zos.closeEntry();  
          bis.close();   
        }  
        
      zos.flush();  
      zos.close();    
      out.clear(); 
      out = pageContext.pushBody();   
%>

    最后两句 out.clear();     out = pageContext.pushBody();   ,如果不加,由于项目采用的框架在请求返回中有调用response.getWriter().write(out),导致抛异常
   java.lang.IllegalStateException: getOutputStream() has already been called for this response;


   网上查了查,说是getWriter和getgetOutputStream不能同时用,又从网上下了Servlet规范,确认了下:
   public ServletOutputStream getOutputStream()
throws IOException
Returns a ServletOutputStream suitable for writing binary data in the
response. The servlet container does not encode the binary data.
Calling flush() on the ServletOutputStream commits the response. Either this
method or getWriter() may be called to write the body, not both.
Returns: a ServletOutputStream for writing binary data
Throws:
IllegalStateException - if the getWriter method has been called on this
response
IOException - if an input or output exception occurred
 看来确实如此;


那么这两句话是什么意思呢?
JSP容器在处理完成请求后会调用releasePageContext方法释放所有的PageContextObject,并且同时调用getWriter方法。由于getWriter方法与在JSP页面中使用流相关的getOutputStream方法冲突,所以会造成这种异常;
pushBody()的作用是保存当前的out对象,并更新PageContext中Page范围内Out对象;

将out对象重置,从而解决了冲突;

注:本文主要参考以下四篇博文:
         http://www.pin5i.com/showtopic-23328.html
         http://alex295111.iteye.com/blog/519004
         http://xiangxingchina.iteye.com/blog/748233
         http://xiaodiandian.iteye.com/blog/662995

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值