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