22

I build a very large POI workbook, on my web server. Holding the entire workbook in memory , will not scale for multiple concurrent requests. Is there a way i can progressively write the workbook to the servlet output stream. That should reduce the response time , as well as make the process memory efficient.

4

5 回答 5

10

如果您要生成 Excel 2007 (xslx),那么您可以调整 BigGridDemo.java 的方法,如下所述:http://web.archive.org/web/20110821054135/http: //www.realdevelopers.com/blog /代码/excel

解决方案是让 POI 仅生成一个容器 xslx 作为模板,并将实际的电子表格数据作为 XML 流式传输到 zip 输出流中。然后由您来简化 XML 生成。

于 2010-06-19T16:39:39.403 回答
7

自从编写了其余答案以来,情况已大大改善-流式传输现在是 Apache Poi 的一部分。

请参阅SXSSFWorkbook类和此处的文档。它在工作表上使用流式窗口,将窗口外的旧行刷新到临时文件。

这是基于hlg 的 answerBigGridDemo中使用的方法,但现在是官方发行版的一部分。

这是文档中的示例:

public static void main(String[] args) throws Throwable {
    // keep 100 rows in memory, exceeding rows will be flushed to disk
    SXSSFWorkbook wb = new SXSSFWorkbook(100); 
    Sheet sh = wb.createSheet();
    for(int rownum = 0; rownum < 1000; rownum++){
        Row row = sh.createRow(rownum);
        for(int cellnum = 0; cellnum < 10; cellnum++){
            Cell cell = row.createCell(cellnum);
            String address = new CellReference(cell).formatAsString();
            cell.setCellValue(address);
        }

    }

    // Rows with rownum < 900 are flushed and not accessible
    for(int rownum = 0; rownum < 900; rownum++){
      Assert.assertNull(sh.getRow(rownum));
    }

    // ther last 100 rows are still in memory
    for(int rownum = 900; rownum < 1000; rownum++){
        Assert.assertNotNull(sh.getRow(rownum));
    }

    FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");
    wb.write(out);
    out.close();

    // dispose of temporary files backing this workbook on disk
    wb.dispose();
}
于 2017-04-21T00:42:41.640 回答
3

不幸的是,当没有顺序数据时,这是不可能的。我建议寻找另一种格式,例如 CSV 或 XML。两者都可以顺序写出。如果它来自数据库,它甚至可以更高效地完成,因为一个体面的数据库具有内置设施,可以有效地导出到这些格式。您只需要将字节从一侧流式传输到另一侧。

于 2010-04-20T12:15:51.763 回答
1

您是否尝试过直接使用 HttpServletResponse.getOutputStream() 的 write 方法?

请看以下示例:

 HSSFWorkbook wb = new HSSFWorkbook();
 HSSFSheet sheet = wb.createSheet("new sheet");
 ...
 OutputStream out = response.getOutputStream();
 wb.write(out);
 out.close();
于 2010-10-20T12:49:17.110 回答
0

如果您使用JExcel 它有示例代码来读取和从 Servlet 读取流代码。 http://jexcelapi.sourceforge.net/resources/faq/

这个 API 的唯一缺点是它只支持 Excel 2003(包括 Excel 2003)。

使用 POI - 您可以不创建文件并将文件的字节提供给 servlet 输出流吗?

于 2010-04-21T01:17:20.473 回答