代码之家  ›  专栏  ›  技术社区  ›  Deviling Master

iTextPDF:将静态模板叠加到PDF的所有页面

  •  1
  • Deviling Master  · 技术社区  · 7 年前

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

    在这次编辑中,我使用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 回复  |  直到 7 年前
        1
  •  2
  •   mkl    7 年前

    不要这样做

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

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

    但确实如此

    stamper.close();
    

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

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

    contentReader.close();
    

    也就是说,您应该只导入一次模板页面,然后重用 PdfImportedPage templatePage .


    编辑问题后:

    请不要在关闭母版之前关闭模板pdf阅读器。一、 e.移动线路

    templateReader.close();
    

    之后

    压模。关闭();
    
        2
  •  1
  •   Deviling Master    7 年前

    根据@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();
    
    推荐文章