Java iText 没有关联 PdfWriter 用于间接访问

Java iText There is no associate PdfWriter for making indirects

我有以下方法

   void scale(PdfDocument pdfDocument, Rectangle pageSize, Rectangle pageBodySize) {
    int n = pdfDocument.getNumberOfPages();

    for (int i = 1; i <= n; i++) {
        PdfPage page = pdfDocument.getPage(i);

        MarginFinder marginFinder = new MarginFinder();
        PdfCanvasProcessor pdfCanvasProcessor = new PdfCanvasProcessor(marginFinder);
        pdfCanvasProcessor.processPageContent(page);
        Rectangle boundingBox = marginFinder.getBoundingBox();
        if (boundingBox == null || boundingBox.getWidth() == 0 || boundingBox.getHeight() == 0) {
            System.err.printf("Cannot scale page %d contents with bounding box %s\n", i, boundingBox);
            continue;
        } else {
            // Scale and move content into A4 with margin
            double scale = 0, xDiff = 0, yDiff = 0;
            double xScale = pageBodySize.getWidth() / boundingBox.getWidth();
            double yScale = pageBodySize.getHeight() / boundingBox.getHeight();
            if (xScale < yScale) {
                yDiff = boundingBox.getHeight() * (yScale / xScale - 1) / 2;
                scale = xScale;
            } else {
                xDiff = boundingBox.getWidth() * (xScale / yScale - 1) / 2;
                scale = yScale;
            }

            AffineTransform transform = AffineTransform.getTranslateInstance(pageBodySize.getLeft() + xDiff, pageBodySize.getBottom() + yDiff);
            transform.scale(scale, scale);
            transform.translate(-boundingBox.getLeft(), -boundingBox.getBottom());

            new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
                    .concatMatrix(transform);

        }
        page.setMediaBox(pageSize);
        page.setCropBox(pageSize);
    }
}

此方法在这段代码中 invoked/called :

  ByteArrayOutputStream mergedPdfStream = new ByteArrayOutputStream();
    PdfDocument mergedPdf = new PdfDocument(new PdfWriter(mergedPdfStream));

    for (PdfDocument doc : pdfDocuments) {
        int n = doc.getNumberOfPages();
      
        for (int i = 1; i <= n; i++) {
       
            PdfPage page = doc.getPage(i).copyTo(mergedPdf);
            mergedPdf.addPage(page);
          
        }
        Rectangle pageSize = PageSize.A4;
        Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
        scale(doc, pageSize, pageBodySize);
    }

   

    mergedPdf.close();

但是,当它最后执行这段代码时

 new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
                .concatMatrix(transform);

它抛出一个 PDF 异常没有关联的 PdfWriter 用于间接访问:

 com.itextpdf.kernel.PdfException: There is no associate PdfWriter for making indirects.
at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:228) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:248) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfPage.newContentStream(PdfPage.java:1186) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfPage.newContentStreamBefore(PdfPage.java:244) ~[kernel-7.1.1.jar:?]

我该如何解决这个问题?我做错了什么吗?

你打电话

scale(doc, pageSize, pageBodySize);

对于 pdfDocuments 中的每个 PdfDocument doc。因此,将页面复制到mergedPdf后,您尝试缩放源文档中的页面。您无法在源 PdfDocument 实例打开时缩放页面 read-only(即只有 PdfReader,没有 PdfWriter),这样做 after 复制也没有意义,因为您肯定想缩放结果 mergedPdf 中的内容,而不是源中的内容。

因此,移动方块

Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(doc, pageSize, pageBodySize);

在外部 for 循环体之后,将最后一行替换为

scale(mergedPdf, pageSize, pageBodySize);

缩放生成的合并 PDF。