将POI工作簿流式传输到servlet输出流

时间:2010-04-20 08:49:03

标签: java servlets apache-poi

我在我的网络服务器上构建了一个非常大的POI工作簿。将整个工作簿保存在内存中,不会扩展多个并发请求。有没有办法可以逐步将工作簿写入servlet输出流。这应该减少响应时间,并使进程内存有效。

5 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:4)

由于其他答案都已编写,因此情况有了很大改善 - Streaming现在是Apache Poi的一部分。

请参阅SXSSFWorkbook课程和documentation here。它在工作表上使用一个流窗口,将窗口外的旧行刷新为临时文件。

这是基于hlg's answer中使用的BigGridDemo方法,但现在是官方发布的一部分。

以下是文档中的示例:

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();
}

答案 2 :(得分:3)

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

答案 3 :(得分:0)

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

此API的唯一不足之处似乎是它仅支持Excel 2003。

使用POI - 你能不创建文件并将文件的字节提供给servlet输出流?

答案 4 :(得分:0)

您是否尝试将write方法直接用于HttpServletResponse.getOutputStream()?

请查看以下示例:

 HSSFWorkbook wb = new HSSFWorkbook();
 HSSFSheet sheet = wb.createSheet("new sheet");
 ...
 OutputStream out = response.getOutputStream();
 wb.write(out);
 out.close();