1

我正在尝试从一些数据库数据中组装一个 CSV 文件,并将其从我的 Spring MVC 控制器(和相关服务)发送到客户端。我正在使用 SuperCSV 来处理写入和输出: http ://supercsv.sourceforge.net/

所以,这里是控制器方法:

@RequestMapping(value="/getFullReqData.html", method = RequestMethod.GET)
public void getFullData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws IOException{
    logger.info("INFO:  ******************************Received request for full Req data dump");

    List<Requirement> allRecords = reqService.getFullDataSet(ProjectService.getProjectID((String)session.getAttribute("currentProject")));
    response.setContentType("text/csv;charset=utf-8"); 
    response.setHeader("Content-Disposition","attachment; filename=nistData.csv");
    OutputStream fout= response.getOutputStream();  
    OutputStream bos = new BufferedOutputStream(fout);   
    OutputStreamWriter outputwriter = new OutputStreamWriter(bos); 

    ICsvBeanWriter writer = new CsvBeanWriter(outputwriter, CsvPreference.EXCEL_PREFERENCE);
    try {
      final String[] header = new String[] { 
              "ReqID", 
              "ColName1",
              "ColName2",
              "ColName3",
              "ColName4",
              "ColName5", 
              "ColName6",
              "ColName7",
              "ColName8",                                 
              "ColName9",
              "ColName10" };

      // the actual writing
      writer.writeHeader(header);

      for(Requirement aCR : allRecords){
          writer.write(aCR, header);
      }

    } finally {
        writer.close();
    }
};

这实际上是向前推进并获得对触发 csv 文件下载的客户端浏览器的响应。

两个问题:

1)我得到一堆服务器端异常吐出(下)

2) CSV 文件中只有标题,没有数据,尽管 allRecords 列表在调试器中显示为完全填充。

我希望填充失败是由异常引起的,但我很怀疑。异常跟踪:

SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:633)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:214)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:105)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:105)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:182)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:123)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
at org.apache.jsp.error_jsp._jspService(error_jsp.java:102)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

异常看起来会传递,因为每次调用此方法我都会看到 4 次。

我发现的所有文档中都有人将他们的 response.getOutputStream() 嵌入到 scriptlet 中,而不是放在 servlet 中。我上面提到的方法是在 Spring MVC 控制器内部,所以建议“将它移到 servlet!” 似乎不适用于这里。据我所知,我只调用了一次 response.getOutputStream() ,并且该方法在第一次调用时就崩溃了。

我难住了。帮助?

4

2 回答 2

7

您的流程可能在请求映射方法的某处引发异常 - 可能在writer.write(aCR, header);其中然后转到 finally 块,关闭响应流,然后异常冒泡到 servlet,它试图通过错误页面处理它(检查你的web.xml error-pagetags) ,因为响应流已关闭,因此无法干净地呈现错误 jsp,因此您会看到异常消息。

如果您可以在控制器中捕获异常并打印堆栈跟踪以查看在写入输出流时控制器中可能出现的问题,那就太好了。

于 2012-09-07T21:14:49.963 回答
0

你能不能让它与 printWriter 一起工作:

    response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".xls\"");
    PrintWriter out = response.getWriter();
于 2012-09-08T01:13:14.953 回答