使用 Spring 在 Docker 中引导 Java 生成 Apache POI xlsx 文件
Generating Apache POI xlsx file with Spring Boot Java in Docker
我有使用 iTextPdf 生成 PDF 的应用程序,现在我添加了 Apache POI 以在相同数据上生成 Excel 文件。前端是 jQuery 的 JS,后端是 Java 11 (openJDK) 和 Spring Boot,Apache POI 5.0。
问题是 运行 在 IDE 中一切正常。文件生成并下载没有问题。当我 运行 apps docker 容器时出现问题。如果我尝试生成 Excel 文件,我会收到错误消息:java.io.IOException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
with no "Caused by"。
我使用 ByteArrayOutputStream 和 OutputStream 生成 xlsx 文件并在浏览器中下载它。我不尝试将文件存储在某个文件夹中,也不使用 Docker 卷。也许 Apache POI 在生成文件时使用了一些临时文件夹?在 Docker?
的 运行 秒内无法执行此操作
提前致谢。
控制器:
try {
Workbook workbook = excelGenerators.getExcelWorkbook(filteredList);
ByteArrayOutputStream boas = new ByteArrayOutputStream();
try {
workbook.write(boas);
} finally {
boas.close();
}
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition","attachment; filename=report.xlsx");
response.setContentLength(boas.size());
OutputStream os = response.getOutputStream();
boas.writeTo(os);
os.flush();
os.close();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
Excel发电机:
public Workbook getExcelWorkbook(List<FullOrder> orderList) {
XSSFWorkbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("SHEET ONE");
sheet.createFreezePane(0, 1);
sheet.setColumnWidth(0, 16000);
...
CellStyle headerStyle = sheet.getWorkbook().createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.AQUA.index);
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setAlignment(HorizontalAlignment.CENTER);
XSSFFont font = workbook.createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 12);
font.setBold(true);
headerStyle.setFont(font);
Row header = sheet.createRow(0);
Cell headerCell = header.createCell(0);
headerCell.setCellValue("Klientas");
headerCell.setCellStyle(headerStyle);
...
CellStyle singleOrderCellStyle = workbook.createCellStyle();
singleOrderCellStyle.setWrapText(true);
singleOrderCellStyle.setAlignment(HorizontalAlignment.LEFT);
AtomicInteger rowCount = new AtomicInteger(1);
orderList.forEach(order -> {
Row row = sheet.createRow(rowCount.get());
Cell cell = row.createCell(0);
cell.setCellValue(order.getClient().getLabel());
cell.setCellStyle(singleOrderCellStyle);
...
rowCount.getAndIncrement();
});
CellStyle totalStyle = sheet.getWorkbook().createCellStyle();
totalStyle.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.index);
totalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
totalStyle.setAlignment(HorizontalAlignment.CENTER);
XSSFFont fontTotal = workbook.createFont();
fontTotal.setFontName("Arial");
fontTotal.setFontHeightInPoints((short) 12);
fontTotal.setBold(true);
totalStyle.setFont(fontTotal);
Row totalRow = sheet.createRow(rowCount.get());
Cell cell = totalRow.createCell(0);
cell = totalRow.createCell(1);
cell = totalRow.createCell(2);
cell = totalRow.createCell(3);
cell.setCellValue(totalCount[0]);
cell.setCellStyle(totalStyle);
cell = totalRow.createCell(4);
cell = totalRow.createCell(5);
cell.setCellValue(Double.parseDouble(decimalFormat.format(totalSum[0]).replace(',', '.')));
cell.setCellStyle(totalStyle);
return workbook;
}
我用 logger.error(e.getClass() + ": " + e.getMessage() + ": " + e.getCause(), e);
更改了 catch,现在堆栈跟踪如下所示:
2021-05-17 12:09:34.060 ERROR 1 --- [io-8080-exec-10] c.s.l.controller.ManagementController : class org.apache.poi.ooxml.POIXMLException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
...
Caused by: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
at org.apache.poi.ooxml.POIXMLFactory.newDocumentPart(POIXMLFactory.java:111) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.ooxml.POIXMLDocumentPart.createRelationship(POIXMLDocumentPart.java:588) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 95 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
at org.apache.poi.xssf.usermodel.XSSFFactory.createDocumentPart(XSSFFactory.java:56) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.ooxml.POIXMLFactory.newDocumentPart(POIXMLFactory.java:109) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 96 common frames omitted
Caused by: java.lang.NoSuchMethodError: org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont.addNewFamily()Lorg/openxmlformats/schemas/spreadsheetml/x2006/main/CTIntProperty;
at org.apache.poi.xssf.usermodel.XSSFFont.setFamily(XSSFFont.java:602) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.usermodel.XSSFFont.setFamily(XSSFFont.java:614) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.createDefaultFont(StylesTable.java:765) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.initialize(StylesTable.java:716) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.<init>(StylesTable.java:130) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 102 common frames omitted
在将与 apache poi 相关的 jars 添加或更改为版本 3.17 后,我收到另一个错误:
java.lang.NoClassDefFoundError: Could not initialize class org.apache.poi.xssf.model.SharedStringsTable
解决方案是将 apache poi 版本降低到 3.17 版本并将 xmlbeans 版本降低到 2.6.0
我有使用 iTextPdf 生成 PDF 的应用程序,现在我添加了 Apache POI 以在相同数据上生成 Excel 文件。前端是 jQuery 的 JS,后端是 Java 11 (openJDK) 和 Spring Boot,Apache POI 5.0。
问题是 运行 在 IDE 中一切正常。文件生成并下载没有问题。当我 运行 apps docker 容器时出现问题。如果我尝试生成 Excel 文件,我会收到错误消息:java.io.IOException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
with no "Caused by"。
我使用 ByteArrayOutputStream 和 OutputStream 生成 xlsx 文件并在浏览器中下载它。我不尝试将文件存储在某个文件夹中,也不使用 Docker 卷。也许 Apache POI 在生成文件时使用了一些临时文件夹?在 Docker?
提前致谢。
控制器:
try {
Workbook workbook = excelGenerators.getExcelWorkbook(filteredList);
ByteArrayOutputStream boas = new ByteArrayOutputStream();
try {
workbook.write(boas);
} finally {
boas.close();
}
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition","attachment; filename=report.xlsx");
response.setContentLength(boas.size());
OutputStream os = response.getOutputStream();
boas.writeTo(os);
os.flush();
os.close();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
Excel发电机:
public Workbook getExcelWorkbook(List<FullOrder> orderList) {
XSSFWorkbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("SHEET ONE");
sheet.createFreezePane(0, 1);
sheet.setColumnWidth(0, 16000);
...
CellStyle headerStyle = sheet.getWorkbook().createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.AQUA.index);
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setAlignment(HorizontalAlignment.CENTER);
XSSFFont font = workbook.createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 12);
font.setBold(true);
headerStyle.setFont(font);
Row header = sheet.createRow(0);
Cell headerCell = header.createCell(0);
headerCell.setCellValue("Klientas");
headerCell.setCellStyle(headerStyle);
...
CellStyle singleOrderCellStyle = workbook.createCellStyle();
singleOrderCellStyle.setWrapText(true);
singleOrderCellStyle.setAlignment(HorizontalAlignment.LEFT);
AtomicInteger rowCount = new AtomicInteger(1);
orderList.forEach(order -> {
Row row = sheet.createRow(rowCount.get());
Cell cell = row.createCell(0);
cell.setCellValue(order.getClient().getLabel());
cell.setCellStyle(singleOrderCellStyle);
...
rowCount.getAndIncrement();
});
CellStyle totalStyle = sheet.getWorkbook().createCellStyle();
totalStyle.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.index);
totalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
totalStyle.setAlignment(HorizontalAlignment.CENTER);
XSSFFont fontTotal = workbook.createFont();
fontTotal.setFontName("Arial");
fontTotal.setFontHeightInPoints((short) 12);
fontTotal.setBold(true);
totalStyle.setFont(fontTotal);
Row totalRow = sheet.createRow(rowCount.get());
Cell cell = totalRow.createCell(0);
cell = totalRow.createCell(1);
cell = totalRow.createCell(2);
cell = totalRow.createCell(3);
cell.setCellValue(totalCount[0]);
cell.setCellStyle(totalStyle);
cell = totalRow.createCell(4);
cell = totalRow.createCell(5);
cell.setCellValue(Double.parseDouble(decimalFormat.format(totalSum[0]).replace(',', '.')));
cell.setCellStyle(totalStyle);
return workbook;
}
我用 logger.error(e.getClass() + ": " + e.getMessage() + ": " + e.getCause(), e);
更改了 catch,现在堆栈跟踪如下所示:
2021-05-17 12:09:34.060 ERROR 1 --- [io-8080-exec-10] c.s.l.controller.ManagementController : class org.apache.poi.ooxml.POIXMLException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
...
Caused by: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException
at org.apache.poi.ooxml.POIXMLFactory.newDocumentPart(POIXMLFactory.java:111) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.ooxml.POIXMLDocumentPart.createRelationship(POIXMLDocumentPart.java:588) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 95 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
at org.apache.poi.xssf.usermodel.XSSFFactory.createDocumentPart(XSSFFactory.java:56) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.ooxml.POIXMLFactory.newDocumentPart(POIXMLFactory.java:109) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 96 common frames omitted
Caused by: java.lang.NoSuchMethodError: org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont.addNewFamily()Lorg/openxmlformats/schemas/spreadsheetml/x2006/main/CTIntProperty;
at org.apache.poi.xssf.usermodel.XSSFFont.setFamily(XSSFFont.java:602) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.usermodel.XSSFFont.setFamily(XSSFFont.java:614) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.createDefaultFont(StylesTable.java:765) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.initialize(StylesTable.java:716) ~[poi-ooxml-4.0.1.jar:4.0.1]
at org.apache.poi.xssf.model.StylesTable.<init>(StylesTable.java:130) ~[poi-ooxml-4.0.1.jar:4.0.1]
... 102 common frames omitted
在将与 apache poi 相关的 jars 添加或更改为版本 3.17 后,我收到另一个错误:
java.lang.NoClassDefFoundError: Could not initialize class org.apache.poi.xssf.model.SharedStringsTable
解决方案是将 apache poi 版本降低到 3.17 版本并将 xmlbeans 版本降低到 2.6.0