【问题标题】:iTextPDF: Superimpose static template to all pages of a PDFiTextPDF:将静态模板叠加到 PDF 的所有页面
【发布时间】:2018-01-06 08:14:40
【问题描述】:

我有一个包含 12 页内容的 PDF。我有另一个 PDF(只有 1 页),它是图形模板。

PDF(内容和模板)均为A4 尺寸,水平方向

对于PDF内容的每一页,我需要应用相同的模板,作为背景

这是我目前制作的代码(我的代码started from here),但我无法检索模板页面并将其应用于每个页面。

public static void main(String[] args) throws IOException, DocumentException {
    // PDF with contents (12 pages)
    File pdfContent = new File("content.pdf");

    // PDF with template (1 page only)
    File pdfTemplate = new File("template.pdf");

    // Where to save the output file
    File output = new File("pdf_output.pdf");
    if (output.exists()) {
        output.delete();
    }

    // Opening reader on content PDF and creating stamper
    PdfReader contentReader = new PdfReader(new FileInputStream(pdfContent));
    PdfStamper stamper = new PdfStamper(contentReader, new FileOutputStream(output));

    // Looping through pages
    for (int i = 1; i <= contentReader.getNumberOfPages(); i++) {
        // Retrieve content page where to apply template
        PdfContentByte contentPage = stamper.getUnderContent(i);

        // Opening template pdf
        PdfReader templateReader = new PdfReader(new FileInputStream(pdfTemplate));

        // Retrieve first page of template pdf (will be applied to content)
        PdfImportedPage templatePage = stamper.getImportedPage(templateReader, 1);

        // Apply template to PDF content
        contentPage.addTemplate(templatePage, 0, 0);

        // Closing reader
        templateReader.close();
    }

    stamper.getWriter().freeReader(contentReader);
    contentReader.close();

    // FIXME calling it throws java.lang.IllegalStateException: Already closed
    // stamper.close();
}

此代码有效,结束时没有任何错误,但生成的 PDF 已损坏且无法显示。

PdfStamper 是获得我正在寻找的结果的正确方法吗?

如何正确使用库以获得结果?


根据@mkl 回复编辑

// Opening reader on content PDF and creating stamper
PdfReader contentReader = new PdfReader(new FileInputStream(pdfContent));
PdfStamper stamper = new PdfStamper(contentReader, new FileOutputStream(output));

// Opening template pdf
PdfReader templateReader = new PdfReader(new FileInputStream(pdfTemplate));
PdfImportedPage templatePage = stamper.getImportedPage(templateReader, 1);
templateReader.close();

// Looping through pages
for (int i = 1; i <= contentReader.getNumberOfPages(); i++) {
    // Retrieve content page where to apply template
    PdfContentByte contentPage = stamper.getUnderContent(i);

    // Apply template to PDF content
    contentPage.addTemplate(templatePage, 0, 0);
}

stamper.close();
contentReader.close();

在这次编辑中,我在最后使用stamper.close() 阅读了模板PDF e。 调用 stamper.close() 时出现此异常

Exception in thread "main" java.lang.IllegalStateException: Already closed
    at com.itextpdf.text.io.ArrayRandomAccessSource.get(ArrayRandomAccessSource.java:64)
    at com.itextpdf.text.io.IndependentRandomAccessSource.get(IndependentRandomAccessSource.java:77)
    at com.itextpdf.text.pdf.RandomAccessFileOrArray.read(RandomAccessFileOrArray.java:225)
    at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:247)
    at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:241)
    at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2665)
    at com.itextpdf.text.pdf.PdfReader.getStreamBytes(PdfReader.java:2631)
    at com.itextpdf.text.pdf.PdfReader.getPageContent(PdfReader.java:2385)
    at com.itextpdf.text.pdf.PdfReaderInstance.getFormXObject(PdfReaderInstance.java:125)
    at com.itextpdf.text.pdf.PdfImportedPage.getFormXObject(PdfImportedPage.java:136)
    at com.itextpdf.text.pdf.PdfReaderInstance.writeAllPages(PdfReaderInstance.java:172)
    at com.itextpdf.text.pdf.PdfWriter.addSharedObjectsToBody(PdfWriter.java:1368)
    at com.itextpdf.text.pdf.PdfStamperImp.close(PdfStamperImp.java:280)
    at com.itextpdf.text.pdf.PdfStamper.close(PdfStamper.java:230)

【问题讨论】:

    标签: java pdf itext


    【解决方案1】:

    根据@mkl 回复,这是工作结果

    // Opening reader on content PDF and creating stamper
    PdfReader contentReader = new PdfReader(new FileInputStream(pdfContent));
    PdfStamper stamper = new PdfStamper(contentReader, new FileOutputStream(output));
    
    // Opening template pdf
    PdfReader templateReader = new PdfReader(new FileInputStream(pdfTemplate));
    PdfImportedPage templatePage = stamper.getImportedPage(templateReader, 1);
    
    // Looping through pages
    for (int i = 1; i <= contentReader.getNumberOfPages(); i++) {
        // Retrieve content page where to apply template
        PdfContentByte contentPage = stamper.getUnderContent(i);
    
        // Apply template to PDF content
        contentPage.addTemplate(templatePage, -40, -40);
    }
    
    stamper.close();
    
    templateReader.close();
    
    contentReader.close();
    

    【讨论】:

    • 感谢分享伙伴。正在寻找一个示例以将一个模板覆盖在另一个 PDF 之上而不会丢失交互(超链接),这对我有很大帮助!
    【解决方案2】:

    别这样

    stamper.getWriter().freeReader(contentReader);
    contentReader.close();
    

    这关闭了压模所基于的阅读器以及压模在关闭时所需的信息。

    但是做

    stamper.close();
    

    在此期间,压模完成 PDF 文档,向其中添加对象交叉引用信息。

    此后您可以并且应该关闭阅读器

    contentReader.close();
    

    话虽如此,您应该只导入一次模板页面,然后重用PdfImportedPage templatePage


    问题编辑后:

    请不要在关闭压模之前关闭模板 pdf 阅读器。 IE。移动线

    templateReader.close();
    

    之后

    stamper.close();
    

    【讨论】:

    • 我使用您的建议编辑了代码(请参阅主要问题的更新部分)。在压模上调用 close() 方法时出现异常
    • 请先移动阅读器close 来电后压模close 来电。一旦您的代码在该星座中工作,您可以通过逐行移动该模板 close 调用(可能与 freeReader 结合使用)来测试是否可以更早关闭模板阅读器(以减少资源使用)称呼。由于这只是针对单个读者,而不是众多读者,因此这种优化尝试完全是可选的。
    猜你喜欢
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多