iTextPDF:将静态模板叠加到PDF

时间:2018-01-06 08:14:41

标签: java pdf itext

我有一个包含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)

2 个答案:

答案 0 :(得分:1)

不要做

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

这将关闭压模所基于的压模以及压模在关闭时需要的信息。

但是

stamper.close();

在此期间,压模最终确定PDF文档,向其添加对象交叉引用信息。

此后你可以而且应该关闭读者

contentReader.close();

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

编辑问题后:

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

templateReader.close();

stamper.close();

答案 1 :(得分:0)

基于@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();