java.lang.IllegalStateException:已为此响应调用了getOutputStream()

时间:2012-12-28 06:30:06

标签: java jsp struts2 download inputstream

这是我的代码,我收到以下异常

HTTP Status 500 - Unable to show problem report: java.lang.IllegalStateException: getOutputStream() has already been called for this response

代码:

WorkbookSettings wbSettings = new WorkbookSettings();    
OutputStream outStream = null;

try
{               
  wbSettings.setLocale(new Locale("en", "EN"));             
  response.setContentType("application/vnd.ms-excel");                  
  outStream= response.getOutputStream();                
  response.setHeader("Content-Disposition", "attachment; filename=/timesheet.xls");             
  WritableWorkbook workbook = Workbook.createWorkbook(outStream, wbSettings);              
  workbook.createSheet("Report", 0);               
  WritableSheet excelSheet = workbook.getSheet(0);              
  service.createLabel(excelSheet);              
  service.createContent(excelSheet);                    
  workbook.write();             
  workbook.close();             
  outStream.flush();               
  outStream.close();                
}               
catch(Exception e)
{
}           
finally
{               
  //outStream.close();      
}   
return "generateReport";

我的Struts.xml看起来像这样

<result type="stream" name="generateReport">                   
 <param name="contentType">"application/vnd.ms-excel"</param>                  
 <param name="inputName">excelstream</param>                  
 <param name="contentDisposition">contentDisposition</param>                   
 <param name="bufferSize">1024</param>              
</result>

在JSP中,我只是给出一个按钮,它给我打开,保存对话框。 点击该按钮后,我得到了例外。

如何避免这种情况?

4 个答案:

答案 0 :(得分:2)

这只是一个语法错误,服务器混淆了如何处理这样的内容类型

<param name="contentType">"application/vnd.ms-excel"</param>

更改为

<param name="contentType">application/vnd.ms-excel</param>

请注意,param值是不带双引号的字符串。

所以,有效的结果是

<result type="stream" name="generateReport">
  <param name="contentType">application/vnd.ms-excel</param>
  <param name="contentDisposition">attachment;filename="timesheet.xls"</param>
  <param name="inputName">excelstream</param>
</result>

操作代码应该初始化excelstream并在返回结果之前提供getter。 workbook不应写入回复,请将其写入ByteArrayOutputStream

private InputStream excelstream;

public InputStream getExcelstream() {
  return excelstream;
}  

public String execute() throws Exception {
  WorkbookSettings wbSettings = new WorkbookSettings();

  try  {  
    ByteArrayOutputStream outstream = new ByteArrayOutputStream();  
    wbSettings.setLocale(new Locale("en", "EN"));        
    WritableWorkbook workbook = Workbook.createWorkbook(outstream, wbSettings);   
    workbook.createSheet("Report", 0);    
    WritableSheet excelSheet = workbook.getSheet(0);    
    service.createLabel(excelSheet);    
    service.createContent(excelSheet);          
    workbook.write();    
    workbook.close();  
    excelstream = new ByteArrayInputStream(outstream.toByteArray());        
  } catch(Exception e) {    
    e.printStackTrace();
    throw e;
  }

  return "generateReport";
}

答案 1 :(得分:2)

绝对删除关闭%&gt;之间的所有空格和换行符并打开&lt;%。在它们之间有空格可以导致自动调用getOutputStream()。因为这些空格或换行符被视为浏览器的输出:它调用getOutputStream()来呈现它们。

它是我发现在JSP中解决此错误的唯一方法。否则,您必须重写将二进制文件作为servlet返回的代码,并使用JSP页面作为启动页面,以便在用户单击按钮时将用户发送到servlet。

答案 2 :(得分:2)

删除关闭%&gt;之间的所有空格和换行符并打开&lt;%和 使用&lt;%@ page trimDirectiveWhitespaces =“true”%&gt;在顶部可以解决这个问题。

答案 3 :(得分:1)

Have you read this?

您需要为inputSteam参数设置inputName,但我无法在您的代码中看到它。

您可以设置ByteArrayOutputStream并将数据存储到ByteArrayInputStream,如下所示

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

/** code to write to outputsteam ***/

ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

您不需要包含这些代码

response.setContentType("application/vnd.ms-excel");    

outStream= response.getOutputStream();

response.setHeader("Content-Disposition", "attachment; filename=/timesheet.xls");

因为你可以在strut动作结果中设置所有这些。