簡體   English   中英

在Docker中用Spring引導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 中運行時一切正常。文件生成並下載沒有問題。 當我運行應用程序 docker 容器時出現問題。 如果我嘗試生成 Excel 文件,我會收到錯誤: java.io.IOException: org.apache.poi.ooxml.POIXMLException: java.lang.reflect.InvocationTargetException ,沒有“由...引起”。 我使用 ByteArrayOutputStream 和 OutputStream 生成 xlsx 文件並在瀏覽器中下載它。 我不嘗試將文件存儲在某個文件夾中,也不使用 Docker 卷。 也許 Apache POI 在生成文件時使用了一些臨時文件夾? 它不能在從 Docker 運行時執行此操作?

提前致謝。

Controller:

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

我遇到了和你一樣的問題,我使用的 Apache POI 版本是 5.2.3。 然后我通過向 Dockerfile 添加這樣的命令找到了解決方案

RUN apk update; apk add --no-cache fontconfig ttf-dejavu

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM