web-dev-qa-db-ja.com

POIワークブックをサーブレット出力ストリームにストリーミングする

Webサーバー上に非常に大きなPOIワークブックを作成します。ブック全体をメモリに保持すると、複数の同時リクエストに対応できなくなります。サーブレット出力ストリームにワークブックを段階的に書き込む方法はありますか?これにより、応答時間が短縮されるだけでなく、プロセスメモリが効率的になります。

19
The Machine

Excel 2007(xslx)を生成しようとしている場合は、ここで説明するようにBigGridDemo.Javaのアプローチを適応させることができます。 http://web.archive.org/web/20110821054135/http://www.realdevelopers .com/blog/code/Excel

解決策は、POIがコンテナxslxをテンプレートとしてのみ生成し、実際のスプレッドシートデータをXMLとしてZip出力ストリームにストリーミングすることです。 XML生成の合理化はあなた次第です。

8
hlg

残りの回答が書かれて以来、状況は大幅に改善されました-ストリーミングは現在ApachePoiの一部です。

SXSSFWorkbook クラス、および ドキュメントはこちら を参照してください。シート上でストリーミングウィンドウを使用し、ウィンドウの外側の古い行を一時ファイルにフラッシュします。

これは、 hlgの回答 で使用されている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();
}
5
Timothy Jones

残念ながら、シーケンシャルデータの手段がない場合、それは不可能です。別の形式を探すことをお勧めします。 CSVまたはXML。どちらも順番に書き出すことができます。それがDBからのものである場合、まともなDBにはそれらの形式に効率的にエクスポートするための機能が組み込まれているため、より効率的に行うことができます。バイトを一方から他方にストリーミングする必要があります。

3
BalusC

JExcel を使用する場合サーブレットとの間でストリームコードを読み取るためのサンプルコードがあります。 http://jexcelapi.sourceforge.net/resources/faq/

このAPIの唯一の欠点は、Excel2003までしかサポートしていないようです。

POIの使用-ファイルを作成して、ファイルのバイトをサーブレット出力ストリームに提供することはできませんか?

0
Romain Hippeau

HttpServletResponse.getOutputStream()に直接書き込むメソッドを試してみましたか?

次の例を見てください。

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