java.lang.IllegalStateException: getOutputStream() has already been called
1 <%@page language="java" contentType="text/html; charset=UTF-8"%> 2 <%@page import="java.util.*,java.io.*"%> 3 <html> 4 <head> 5 <title>下載頁面</title> 6 </head> 7 8 <body> 9 <% 10 response.reset(); //記住要記住reset瀏覽器清空緩存,不然可能會出現亂碼狀況 11 12 OutputStream o=response.getOutputStream(); 13 14 ResourceBundle res = ResourceBundle.getBundle("test"); //test.properties 15 String XLSFile = res.getString("tempFileRootPath") + "/excel"; 16 File fileLoad=new File(XLSFile,"temp.xls"); 17 18 if(fileLoad.exists()) { 19 response.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode("filename文件名", "UTF-8")+".xls");//文件中文名UTF-8 20 response.setContentType("application/vnd.ms-excel"); 21 long fileLength=fileLoad.length(); 22 String length=String.valueOf(fileLength); 23 response.setHeader("Content_Length",length); 24 25 FileInputStream in = new FileInputStream(fileLoad); 26 OutputStream o = null; 27 try{ 28 in = new FileInputStream(fileLoad); 29 30 o = response.getOutputStream(); 31 out.clear(); 32 out = pageContext.pushBody(); // 33 34 int n=0; 35 byte b[]=new byte[500]; 36 37 while((n=in.read(b))!=-1) { 38 o.write(b,0,n); 39 } 40 o.flush(); 41 42 } catch (Exception e) { 43 out.write("文件導出異常" + e.toString()); 44 } finally { 45 if(in != null) { 46 try { 47 in.close(); 48 } catch(Exception e) {} 49 } 50 if(o != null) { 51 try { 52 o.close(); 53 } catch(Exception e) {} 54 } 55 } 56 } else { 57 out.write("未找到導出的臨時文件"); 58 } 59 60 %> 61 62 </body> 63 </html>
緣由:html
在tomcat中jsp編譯成servlet以後在函數_jspService(HttpServletRequest request, HttpServletResponse response)的最後
有一段這樣的代碼
finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
}
這裏是在釋放在jsp中使用的對象,會調用response.getWriter(),由於這個方法是和
response.getOutputStream()相沖突的!因此會出現以上異常 IllegalStateException: getOutputStream() has already been called。
jsp中出現此錯誤通常都是在jsp中使用了輸出流(如輸出圖片驗證碼,文件下載等),沒有妥善處理好的緣由。
解決方法:在使用完response.getOutputStream()的後面加上兩句(標黃):java
out.clear(); out = pageContext.pushBody();
附上javax.servlet.jsp.PageContext方法pushBody()
說明:api
public BodyContent pushBody()
- Return a new BodyContent object, save the current "out" JspWriter, and update the value of the "out" attribute in the page scope attribute namespace of the PageContext.
-
- Returns:
- the new BodyContent