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

测试jsp:html

<%@ 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()); } %>

 

调用的下载类:java

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(); * */ } } } }