Apache POI 3.14将SXSSF写入ServletResponse OutputStream正在破坏工作簿JSF

时间:2018-05-01 16:34:20

标签: java excel jsf apache-poi

在我的webapp中,我正在构建SXSSFWorkbook对象以生成每个大约有30-60k条记录的报告。我通过请求首先获取并构建每个SXSSFWorkbook来启动进程。我能够生成报告并打开FileOutputStream将我的对象导出到我的桌面(当然是本地)。但是,我想让用户通过请求(JSF)选择要下载到服务器的报告。当我从servlet响应中提供OutputStream时,我可以下载.xlsx文件,但它告诉我它已被破坏。我做了一些研究,尝试了一些不同的解决方法,但都没有结果。发表是我的代码。我对这里发生的事情感到很茫然。

P.S。我以前生成HSSFWorkbook对象并下载它们但它们开始导致堆空间问题。因此,切换到SXSSFWorkbook。

我的命令按钮                     

                <h:commandButton value="Download Report" styleClass="secondary-button"
                    action="#{backingBean.getLatestReport}"
                    id="thirdReportButton">
                </h:commandButton>

我的行动

public void getLatestReport() throws Exception {
    FacesContext faces = FacesContext.getCurrentInstance();
    String templateName = "Report.xlsx";
    HttpServletResponse response = null;
    OutputStream outputStream = null;
    //workbookForLatestReport is a SXSSFWorkbook object
    try {
        if (workbookForLatestReport != null) {
            response = (HttpServletResponse) faces.getExternalContext()
                    .getResponse();
            response.reset();
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-disposition",
                    "attachment; filename=\"" + templateName + "\"");

            outputStream = response.getOutputStream();
            workbookForLatestReport.write(outputStream);
            outputStream.close();
            workbookForLatestReport.dispose();
        }

        faces.renderResponse();
    } catch (Exception e) {
        throw e;
    }
}

1 个答案:

答案 0 :(得分:0)

最近我成功地完成了类似的任务,所以我可以帮助你。

我刚刚运行了您的代码(在使用Chrome作为浏览器的Payara 4.1上)添加了您在帖子中省略的部分

exchanges = [ccxt.bitfinex(), ccxt.binance(), ccxt.okcoinusd()]

它工作正常并且符合预期。

我有2条建议:

  • 您的命令按钮“调用”@ManagedBean(name = "backingBean") @ViewScoped public class BackingBean { //your command button should call getLatestReport and not getSecondReport() as in your original post public void getLatestReport() throws Exception { FacesContext faces = FacesContext.getCurrentInstance(); String templateName = "Report.xlsx"; HttpServletResponse response = null; OutputStream outputStream = null; //workbookForLatestReport is a SXSSFWorkbook object //MY ADDITION START //I've created SXSSFWorkbook object since your post did't contain this part //100K rows, 100 columns SXSSFWorkbook workbookForLatestReport = new SXSSFWorkbook(SXSSFWorkbook.DEFAULT_WINDOW_SIZE); workbookForLatestReport.setCompressTempFiles(true); SXSSFSheet sheet = workbookForLatestReport.createSheet(); for (int rowNumber = 0; rowNumber < 100000; rowNumber++) { SXSSFRow row = sheet.createRow(rowNumber); for (int columnNumber = 0; columnNumber < 100; columnNumber++) { SXSSFCell cell = row.createCell(columnNumber); cell.setCellValue("ROW " + rowNumber + " COLUMN " + columnNumber); } } //MY ADDITION END try { if (workbookForLatestReport != null) { response = (HttpServletResponse) faces.getExternalContext() .getResponse(); response.reset(); response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment; filename=\"" + templateName + "\""); outputStream = response.getOutputStream(); workbookForLatestReport.write(outputStream); outputStream.close(); workbookForLatestReport.dispose(); } faces.renderResponse(); } catch (Exception e) { throw e; } } } 但是您的托管bean操作名为action="#{backingBean.getSecondReport}"。 检查是否输入错误。
  • 将您的SXSSFWorkbook对象创建代码与我的示例进行比较。是 有什么重要的区别吗?