包含 PDDoucment 的问题

Issues with enclosing PDDoucment

我已经实现了一个将数据打印成 pdf 的程序,但是我遇到了这个问题

java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?

我知道已经发布了类似的问题,但我无法从他们那里找到解决我的问题的方法。我正在做的是我初始化了两个文档,其中一个是主文档(doc),另一个是其余页面,然后我添加到主文档(activeDocument),该服务调用三个不同的函数来添加一个新的第一页第一页,中间的任何页面,最后一页之前和最后一页 page.a 这是我的代码,大部分逻辑都可以忽略,主要是与 PDDocuments 相关的内容,因为那是问题所在

private InputStream generateCardsPDF(String cardNumber,
                                         String generationDate,
                                         StatementSummaryResTypeStatementSummaryResBody resBody,
                                         String pdf) throws IOException, ParseException {


        List<StatementSummaryResTypeStatementSummaryResBodyTransactionsTransaction> transactionList = resBody.getTransactions().getTransaction().stream().limit(50).collect(Collectors.toList());
        PDDocument doc = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
        PDDocumentCatalog docCatalog = doc.getDocumentCatalog();
        PDPage page = docCatalog.getPages().get(0);
        try {
            String fullName = resBody.getStatementHeader().getAddress().getTitle() +
                    " " + resBody.getStatementHeader().getAddress().getFirstName() + " ";
            String fullAddress = "";
            if (resBody.getStatementHeader().getAddress().getMiddleName() != null) {
                fullName = fullName + resBody.getStatementHeader().getAddress().getMiddleName() + " ";
            }

            fullName = fullName + resBody.getStatementHeader().getAddress().getLastName();


            String countryAddress = resBody.getStatementHeader().getAddress().getCity() != null ? resBody.getStatementHeader().getAddress().getCity() : "";
            countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
                    countryAddress.length() > 0 ? ", " + resBody.getStatementHeader().getAddress().getCountry() : "";
            countryAddress += resBody.getStatementHeader().getAddress().getCountry() != null &&
                    countryAddress.length() == 0 ? resBody.getStatementHeader().getAddress().getCountry() : "";

            fullAddress += resBody.getStatementHeader().getAddress().getAddress1() + ONE_LINE;
            fullAddress += resBody.getStatementHeader().getAddress().getAddress2() != null ? resBody.getStatementHeader().getAddress().getAddress2() + ONE_LINE : "";
            fullAddress += resBody.getStatementHeader().getAddress().getAddress3() != null ? resBody.getStatementHeader().getAddress().getAddress3() + ONE_LINE : "";
            fullAddress += countryAddress;

            String header = fullName + ONE_LINE + fullAddress;
            Integer currentIndex = 0;
            Integer count = 0;
            Integer cutOff = 0;
            Integer pageNumber = 1;
            Integer numberOfPages = statementsUtils.calculateNumberOfPages(transactionList, currentIndex, cutOff, count);
            String pageOf;
            PDDocument activeDocument = new PDDocument();
            statementsUtils.setFirstPage(transactionList, resBody, doc, header, maskedCard(cardNumber), generationDate, numberOfPages);
            try {
                while (currentIndex < transactionList.size()) {
                    Boolean fourOrFive = false;
                    Boolean checkpoint = false;
                    Boolean finalPrint = false;
                    if (count == 4) {
                        checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
                        if (checkpoint) {
                            cutOff = currentIndex;
                            fourOrFive = true;
                            pageNumber++;
                            pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                            statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
                            count = 0;
                        }
                    } else if (count == 5) {
                        cutOff = currentIndex;
                        fourOrFive = false;
                        pageNumber++;
                        pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                        statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
                        count = 0;
                    } else if (transactionList.size() <= 2) {
                        finalPrint = true;
                    } else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
                        finalPrint = true;
                        pageNumber++;
                        pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                        if (transactionList.size() - currentIndex + 1 == 5) {
                            statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
                            pageNumber++;
                            pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                            statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
                        } else {
                            statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate);
                        }
                    }

                    if (fourOrFive && !finalPrint)
                        currentIndex = cutOff + 1;
                    else if (finalPrint)
                        currentIndex = transactionList.size();
                    else
                        currentIndex++;

                    if (currentIndex >= 2) count++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (activeDocument != null) {
                    activeDocument.close();
                }
            }
        } catch (IOException e) {

            e.printStackTrace();
        } finally {
            PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
            contentStream.close();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            if (doc != null) {
                doc.save(out);
                doc.close();
            }
            ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
            return in;
        }

    }



  public void setFirstPage( PDDocument doc,....){
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
...
acroForm.flatten();

}

      public void setPreLastPage( PDDocument doc, PDDocument activeDocument....){
     activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
        PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
        PDPage p1 = docCatalog.getPages().get(0);
        PDAcroForm acroForm = docCatalog.getAcroForm();
        ...
        acroForm.flatten();
        PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
        cs.close();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        activeDocument.save(out);
        doc.addPage(p1);
    
    }

      public void setLastPage( PDDocument doc, PDDocument activeDocument....){
     activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
        PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
        PDPage p1 = docCatalog.getPages().get(0);
        PDAcroForm acroForm = docCatalog.getAcroForm();
        ...
        acroForm.flatten();
        PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
        cs.close();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        activeDocument.save(out);
        doc.addPage(p1);
    
    }

      public void addExtraPage( PDDocument doc, PDDocument activeDocument....){
     activeDocument = new PDDocument().load(getClass().getClassLoader().getResourceAsStream(pdf));
        PDDocumentCatalog docCatalog = activeDocument.getDocumentCatalog();
        PDPage p1 = docCatalog.getPages().get(0);
        PDAcroForm acroForm = docCatalog.getAcroForm();
        ...
        acroForm.flatten();
        PDPageContentStream cs = new PDPageContentStream(activeDocument, p1,PDPageContentStream.AppendMode.APPEND, true);
        cs.close();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        activeDocument.save(out);
        doc.addPage(p1);
    
    }

这些函数中有更多的逻辑,但我尝试只添加我认为相关的内容。

我认为问题与其中一个 pdf 的内容流或我关闭、保存等的顺序有关....但我无法弄清楚确切的问题是什么,所以任何建议都会不胜感激。

三个错误在 setPreLastPagesetLastPageaddExtraPage 中:在这些方法中的每一个中,您在各自的局部变量 [=14] 中加载一个新的 PDDocument =],从中取出一个页面并将其添加到相同的 PDDocument doc,然后在离开相应方法时删除 activeDocument 中对该 PDDocument 的所有引用。

删除所有引用允许垃圾回收选择这些 PDDocument 实例并关闭并删除它们。这会拉走复制到 PDDocument doc 的页面下方的数据,导致您在尝试保存 doc.

时观察到的错误

为防止这种情况,要么在添加页面对象之前将页面对象克隆到 doc 中,要么在保存 doc.

之前保持所有这些临时文档处于打开状态

如果有人对解决方案的实际实施感到好奇,我创建了一个空列表。

List<PDDocument> activeDocuments = new ArrayList<PDDocument>();

然后每次我调用其中一种方法时,我都会返回文档并将其存储在列表中,然后在保存原始文档后最后将它们全部关闭。

  while (currentIndex < transactionList.size()) {
                    Boolean fourOrFive = false;
                    Boolean checkpoint = false;
                    Boolean finalPrint = false;
                    if (count == 4) {
                        checkpoint = statementsUtils.reachedCheckpoint(currentIndex, transactionList);
                        if (checkpoint) {
                            cutOff = currentIndex;
                            fourOrFive = true;
                            pageNumber++;
                            pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                            activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
                            count = 0;
                        }
                    } else if (count == 5) {
                        cutOff = currentIndex;
                        fourOrFive = false;
                        pageNumber++;
                        pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                        activeDocuments.add(statementsUtils.addExtraPage(doc, activeDocument, cutOff, fourOrFive, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
                        count = 0;
                    } else if (transactionList.size() <= 2) {
                        finalPrint = true;
                    } else if (transactionList.size() - currentIndex + 1 <= 5) { // count <4? print last page or count >=4 print 4 and check homuch left
                        finalPrint = true;
                        pageNumber++;
                        pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                        if (transactionList.size() - currentIndex + 1 == 5) {
                            activeDocuments.add(statementsUtils.setPreLastPage(doc, activeDocument, currentIndex, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
                            pageNumber++;
                            pageOf = "Page " + pageNumber.toString() + " of " + numberOfPages.toString();
                            activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, transactionList.size() - 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
                        } else {
                            activeDocuments.add(statementsUtils.setLastPage(doc, activeDocument, currentIndex - count + 1, transactionList, resBody, pageOf, pdf, header, maskedCard(cardNumber), generationDate));
                        }
                    }

                    if (fourOrFive && !finalPrint)
                        currentIndex = cutOff + 1;
                    else if (finalPrint)
                        currentIndex = transactionList.size();
                    else
                        currentIndex++;

                    if (currentIndex >= 2) count++;
                }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
            contentStream.close();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            if (doc != null) {
                doc.save(out);
                doc.close();
            }
            for (PDDocument a : activeDocuments)
                a.close();

            if (activeDocument != null) {
                activeDocument.close();
            }
            ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
            return in;
        }