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