【问题标题】:Itext - How to clone pages with acrofields?Itext - 如何使用 acrofields 克隆页面?
【发布时间】:2011-04-28 11:36:01
【问题描述】:

我正在用 Java 编写一个打印 Bingo Cards 的 PDF 文件的程序。每页是一张卡片。为了方便我,我创建了一个带有 acrofields 的模板 PDF 文件,因此程序只需要创建此模板的副本,用数字填充 acrofields,然后将其展平。截至目前,我可以创建 1 张宾果卡。我想在一个 PDF 文件中有多个页面(因此,多张卡片)。但我不知道如何做到这一点。我读到的是 PDFStamper 与一个且只有一个 PDFReader 对象相关联。有没有一种方法可以做到这一点,而无需创建多个 PDF 文件并将它们合并为一个(我上次这样做了,我发现真的很慢)提前谢谢!

【问题讨论】:

    标签: java itext


    【解决方案1】:

    我花了一段时间才弄明白。这不是最有效的编码方式,但本质上它的作用如下:

    • 创建文档
    • 对于带有 acrofield 的每个页面:
    • 复制您的模板
    • 填写表格
    • 展平表格
    • 添加页面

    这是我的实现,您可以尝试修改以满足您的需求:

    private void createPdf() throws Exception {
        Document doc = new Document();
        PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf"));
        doc.open();
    
        PdfReader reader;
        PdfStamper stamper;
        AcroFields form;
        ByteArrayOutputStream baos;
    
        for(int i = 0; i < getTotalPages(); i++) {
            copyPdf(i);
    
            reader = new PdfReader(String.format("%d%s", i, "template.pdf"));
            baos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, baos);
            form = stamper.getAcroFields();
    
            //methods to fill forms
    
            stamper.setFormFlattening(true);
            stamper.close();
    
            reader = new PdfReader(baos.toByteArray());
            copy.addPage(copy.getImportedPage(reader, 1));
        }
    
        doc.close();
    }
    
    private void copyPdf(int currentPage) throws Exception {
        PdfReader reader = new PdfReader("timesheet.pdf");
        Document doc = new Document();
        File file = new File(String.format("%d%s", currentPage, "template.pdf"));
        file.deleteOnExit();
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(file));
        stamper.close();
    }
    

    copyPdf() 方法创建临时文件,用于在不影响整个文档的情况下填写表单。如果您找到了更有效的方法,请告诉我。

    另外,我发现在基于 Intel 的 Mac 与 Windows 计算机上,Mac 的完成速度要快得多。

    如果您不反对获得 iText 参考书,我会推荐 Bruno Lowagie 的“iText in Action, Second Edition”。这是一本很棒的书,很有帮助。

    【讨论】:

    • +1 正是我需要的!谢谢!请注意,不使用 copyPdf 中的 'doc' :)
    • 你根本不需要copyPdf()。即使您这样做了,这也是将文件(恰好是 PDF)从 A 复制到 B 的一种非常低效的方式。您甚至可以对所有不同的 PdfStamper 实例使用相同的 PdfReader,但这很可能会揭示错误。在同一个文件上使用多个阅读器肯定会接近
    • @MarkStorer 我已经使用了这个答案,但我确认您关于PdfReader 的建议完全有效。如果您有能力花费一点内存,您可以加快将整个 PDF 加载到字节数组中并从中创建 PdfReader 对象的速度,或者使用 new PdfReader(reader) 复制初始阅读器。
    【解决方案2】:

    所以,这里的代码没有使用 Zach 的“copyPdf”方法,正如 Mark Storer 和 MaxArt 所建议的那样:

    private void createPdf() throws Exception {
        Document doc = new Document();
        PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf"));
        doc.open();
        
        PdfReader mainReader = new PdfReader("timesheet.pdf");
        
        PdfReader reader;
        ByteArrayOutputStream baos;
        PdfStamper stamper;
        AcroFields form;
        
        for(int i = 0; i < getTotalPages(); i++) {
            
            reader = new PdfReader(mainReader);
            baos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, baos);
            form = stamper.getAcroFields();
            
            //methods to fill forms
            
            stamper.setFormFlattening(true);
            stamper.close();
            
            reader = new PdfReader(baos.toByteArray());
            copy.addPage(copy.getImportedPage(reader, 1));
        }
    
        doc.close();
    }
    

    【讨论】:

    • 我基本上都尝试了这两个答案,但没有运气。我想知道 itext 是什么版本的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多