【问题标题】:SXSSFWorkbook Cannot write data, document seems to have been closed alreadySXSSFWorkbook 无法写入数据,文档似乎已经关闭
【发布时间】:2021-10-25 16:34:19
【问题描述】:

我在将数据写入 SXSSFWorkbook 文件时遇到异常。我可以使用 XSSFWorkbook 做同样的事情,而且效果很好。

java.io.IOException: Cannot write data, document seems to have been closed already
at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:230)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.write(SXSSFWorkbook.java:953)
at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:79)
at org.glassfish.jersey.message.internal.StreamingOutputProvider.writeTo(StreamingOutputProvider.java:61)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266)

这是我的代码。

public static Response createResponseUsingStreaming() throws IOException {
    SXSSFWorkbook workbook = report.generateStreamingExcelReport(100);
    StreamingOutput outputStream = workbook::write;
    final String contentType = "application/vnd.ms-excel";

    Response.ResponseBuilder responseBuilder = Response.ok(outputStream);
    responseBuilder.header("Content-Disposition", "attachment; filename=test");
    responseBuilder.header("Access-Control-Expose-Headers", "Content-Disposition");
    responseBuilder.header("Content-Type", contentType);
    Response response = responseBuilder.build();
    if (null != workbook) {
        workbook.dispose();
        workbook.close();
    }
    return response;
}

public SXSSFWorkbook generateStreamingExcelReport(int rowAccessWindowSize) {
    List<List<String>> rows = createRawData();
    SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(rowAccessWindowSize);

    createExcelSummaryPage(sxssfWorkbook);
    createExcelDetailPage(rows, sxssfWorkbook);

    return sxssfWorkbook;
}

在创建新的 SXSSFWorkbook 时设置了 OPCPackage,想知道在哪里设置为 null。

public final void write(OutputStream stream) throws IOException {
    OPCPackage p = getPackage();
    if(p == null) {
        throw new IOException("Cannot write data, document seems to have been closed already");
    }

    //force all children to commit their changes into the underlying OOXML Package
    // TODO Shouldn't they be committing to the new one instead?
    Set<PackagePart> context = new HashSet<>();
    onSave(context);
    context.clear();

    //save extended and custom properties
    getProperties().commit();

    p.save(stream);
}

【问题讨论】:

  • 您是否检查过createExcelSummaryPagecreateExcelDetailPage 是否正在关闭工作簿?否则,ResponseResponse.ResponseBuilder 到底是什么?如果这些是异步的,那么当responseBuilder.build() 调用workbook::write 时,工作簿可能已经关闭。
  • 否,createExcelSummaryPage 或 createExcelDetailPage 没有关闭工作簿。我正在使用 REST API 下载报告,而 Response 和 Response.ResponseBuilder 是我用来构建响应的 javax 库。
  • 所以ResponseResponse.ResponseBuilderjavax.ws.rs.core.*-classes?然后我建议标记java-ee 以吸引Java EE 用户回答这个问题。因为我没有使用Java EE,所以我无能为力。

标签: java apache-poi sxssf


【解决方案1】:

如果您可以使用XSSFWorkbook,您应该可以使用您的XSSFWorkbook 使用SXSSFWorkbook

这是一个简单的工作示例:

public void createExcelFileUsingSXSSFWorkbook(XSSFWorkbook wb) {

    SXSSFWorkbook wbSXSSF = new SXSSFWorkbook(wb);

    try {
        Path path = Files.createFile(Path.of("test.xlsx"));
        try (OutputStream outputStream = Files.newOutputStream(path)) {
            wbSXSSF.write(outputStream);
            wbSXSSF.close();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    } catch (IOException e1) {
        e1.printStackTrace();
    }

}

【讨论】:

    【解决方案2】:

    我能够按以下方式解决此问题

    outputStream = outputStream1 -> {
                sxssfWorkbook.write(outputStream1);
                sxssfWorkbook.dispose();
                sxssfWorkbook.close();
            };
    

    工作簿正在写入 responseBuilder.build(),所以我必须将 write()、dispose() 和 close() 烘焙到输出流中才能正常工作

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 2021-06-07
      • 2017-12-13
      • 2013-10-28
      • 1970-01-01
      • 2016-03-26
      • 1970-01-01
      • 2015-03-26
      • 2012-04-30
      相关资源
      最近更新 更多