jsp实现文件下载,out = pageContext.pushBody();out.close();不用写到jsp中

本文详细介绍了使用JSP实现文件下载的方法,通过自定义DocumentFile类处理文件读取与输出,兼容WebSphere和Tomcat环境,避免了JspWriter默认输出流的问题。

测试jsp:

<%@ page contentType="text/html; charset=gbk" %>
<%
try{
 com.enfo.intrust.web.DocumentFile file = new com.enfo.intrust.web.DocumentFile(pageContext);
 String file_name = "d:/中国人.txt";
 String name = "中国人.txt";
 file.downloadFile(file_name,name);
}catch(Exception e){
 throw new Exception(e.getMessage());
}
%>

 

调用的下载类:

package com.enfo.intrust.web;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;

public class DocumentFile {
    private PageContext pageContext;
    public DocumentFile() {}
    public DocumentFile(PageContext in_pageContext) {
        try {
            pageContext = in_pageContext;
        } catch (Exception e) {
            pageContext = null;
        }
    }
    
    private String Encode(String in) {
        try {
            return new String(in.getBytes("GBK"), "ISO-8859-1");
        } catch (Exception e) {
            return in;
        }
    }

    /**
     * @param strFile 文件路径
     * @param name 文件名,包含后缀
     * */
    public void downloadFile(String filePath, String fileName)throws Exception {
        java.io.File file = new java.io.File(filePath);
        if (!file.exists()) throw new Exception("file not exist");
        /**
         *取消JSP默认的输出流:javax.servlet.jsp.JspWriter
         */
        JspWriter out = pageContext.getOut();
        out.clear();
        /**
         * Websphere发布环境中,不能要下面这一行代码
         * 主要是Weblogic或Websphere发布环境中问题,与tomcat不同
         * 此处pushBody会将out引用一个新对象ContextBody的实例,ContextBody是JspWriter的子类
         */
        //out = pageContext.pushBody();

        /**
         * response.getWriter()取得的是java.io.PrintWriter,输出以字符为单位;
         * response.getOutputStream()取得的是javax.servlet.serlvetoutputstream,输出以字节为单位;
         * 采用response的输出流:ServletOutputStream
         * 从本地文件的输入流读取数据通过这个字节输出流输出
         */
        HttpServletResponse response = (HttpServletResponse) (pageContext.getResponse());
        response.reset();    
        response.setContentType("application/octet-stream");
        response.addHeader("Content-disposition", Encode("attachment;filename=" + fileName));
        DataInputStream dis = null;
        OutputStream os = null;//jsp不用默认的out内置对象,而采用这个字节输出流
        try {
            dis = new DataInputStream(new FileInputStream(file));
            os = response.getOutputStream();
            byte[] buf = new byte[1024];
            int curLen=0;
            System.out.println("start to download:"+fileName);
            while((curLen=dis.read(buf))>=0){
                os.write(buf, 0, curLen);
                os.flush();
            }
            System.out.println("download success");
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("download error");
        } finally {
            if(os != null)
                os.close();
            if(dis != null)
                dis.close();
            if(out != null)
            {
                 //out.close();
                /**
                 *jsp引擎中,在每个jsp结束后都会自动释放掉jsp所有内置对象,包括out;如果这里手动人为的把out这个jsp内置对象关闭了,
                 *后面jsp引擎释放它时就会报错提示Stream closed;
                 *但是在websphere发布环境中不会,应该是容器在释放对象前进行过判断,这里体现了websphere容器的容错性
                 *测试:在jsp中java代码区直接写一句:out.close();打开这个jsp,后台会直接报错;
                 *所以,不要在jsp中调用out.close()手动关闭jsp这个out内置对象;
                 * 除非:
                 * out = pageContext.pushBody();
                 * out.close();
                 * 这样不会报错,是因为:
                 * 一开始out=pageContext.getOut()得到的是jsp内置out对象,后来pushBody得到的是一个新的ContextBody对象,他们是二个对象
                 * ContextBody是JspWriter的子类;即:jsp内置out对象是父,pushbody得到的是子,
                 * 所以这里的out.close()其实不是close掉jsp的内置out对象,而是ContextBody的实例对象;
                 * 总结:为了在tomcat和websphere中的通用:
                 * 不要写out = pageContext.pushBody();也不要手动调用 out.close();
                 * */
            }
        }
    }

}

 

转载于:https://www.cnblogs.com/tapt/p/10119446.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值