java - IText 将文档与 acrofields 合并

标签 java adobe itext

我目前有一个 PdfReader 和一个 PdfStamper,我正在用它们填写 acrofields。我现在必须将另一个 pdf 复制到我一直在填写的表格的末尾,当我这样做时,我在复制的新表格上丢失了 acrofield。这是代码。

public static void addSectionThirteenPdf(PdfStamper stamper, Rectangle pageSize, int pageIndex){
     PdfReader reader = new PdfReader(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/documents/Section13.pdf"));
     AcroFields fields = reader.getAcroFields();

     fields.renameField("SecurityGuidancePage3", "SecurityGuidancePage" + pageIndex);

     stamper.insertPage(pageIndex, pageSize);
     stamper.replacePage(reader, 1, pageIndex);
}

我创建原始文档的方式是这样的。

     OutputStream output = FacesContext.getCurrentInstance().getExternalContext().getResponseOutputStream();

     PdfReader pdfTemplate = new PdfReader(FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("/resources/documents/dd254.pdf"));

     PdfStamper stamper = new PdfStamper(pdfTemplate, output);
     stamper.setFormFlattening(true);

     AcroFields fields = stamper.getAcroFields();

有没有办法使用第一段代码合并并将两个 acrofields 合并在一起?

最佳答案

根据您的具体需求,可能会出现不同的情况,但无论如何:您做错了。您应该使用 PdfCopyPdfSmartCopy 来合并文档。

下面将解释不同的场景 video tutorial .

您可以在 iText sandbox 中找到大部分示例.

合并不同的表单(具有不同的字段)

如果您想合并不同的 表单而不展平它们,您应该像在MergeForms 中所做的那样使用PdfCopy示例:

public void createPdf(String filename, PdfReader[] readers) throws IOException, DocumentException {
    Document document = new Document();
    PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
    copy.setMergeFields();
    document.open();
    for (PdfReader reader : readers) {
        copy.addDocument(reader);
    }
    document.close();
    for (PdfReader reader : readers) {
        reader.close();
    }
}

在这种情况下,readers 是一个 PdfReader 实例数组,其中包含不同 表单(具有不同的字段名称),因此我们使用 PdfCopy 并确保我们不会忘记使用 setMergeFields() 方法,否则不会复制字段。

合并相同的表单(具有相同的字段)

在这种情况下,我们需要重命名字段,因为我们可能希望在不同的页面上使用不同的值。在 PDF 中,一个字段只能有一个值。如果您合并相同的表单,您将拥有同一字段的多个可视化效果,但每个可视化效果将显示相同的值(因为在现实中,只有一个字段)。

让我们来看看MergeForms2示例:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    Document document = new Document();
    PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
    copy.setMergeFields();
    document.open();
    List<PdfReader> readers = new ArrayList<PdfReader>();
    for (int i = 0; i < 3; ) {
        PdfReader reader = new PdfReader(renameFields(src, ++i));
        readers.add(reader);
        copy.addDocument(reader);
    }
    document.close();
    for (PdfReader reader : readers) {
        reader.close();
    }
}

public byte[] renameFields(String src, int i) throws IOException, DocumentException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    Set<String> keys = new HashSet<String>(form.getFields().keySet());
    for (String key : keys) {
        form.renameField(key, String.format("%s_%d", key, i));
    }
    stamper.close();
    reader.close();
    return baos.toByteArray();
}

如您所见,renameFields() 方法在内存中创建了一个新文档。该文档使用 PdfSmartCopy 与其他文档合并。如果您在此处使用 PdfCopy,您的文档将变得臃肿(我们很快就会发现这一点)。

合并扁平化表单

FillFlattenMerge1 ,我们使用 PdfStamper 填写表格。结果是保存在内存中并使用 PdfCopy 合并的 PDF 文件。虽然如果您要合并不同的表单,这个示例很好,但这实际上是一个关于如何不这样做的示例(如 video tutorial 中所述)。

FillFlattenMerge2显示如何合并正确填写和展平的相同表格:

public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
    Document document = new Document();
    PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
    document.open();
    ByteArrayOutputStream baos;
    PdfReader reader;
    PdfStamper stamper;
    AcroFields fields;
    StringTokenizer tokenizer;
    BufferedReader br = new BufferedReader(new FileReader(DATA));
    String line = br.readLine();
    while ((line = br.readLine()) != null) {
        // create a PDF in memory
        baos = new ByteArrayOutputStream();
        reader = new PdfReader(SRC);
        stamper = new PdfStamper(reader, baos);
        fields = stamper.getAcroFields();
        tokenizer = new StringTokenizer(line, ";");
        fields.setField("name", tokenizer.nextToken());
        fields.setField("abbr", tokenizer.nextToken());
        fields.setField("capital", tokenizer.nextToken());
        fields.setField("city", tokenizer.nextToken());
        fields.setField("population", tokenizer.nextToken());
        fields.setField("surface", tokenizer.nextToken());
        fields.setField("timezone1", tokenizer.nextToken());
        fields.setField("timezone2", tokenizer.nextToken());
        fields.setField("dst", tokenizer.nextToken());
        stamper.setFormFlattening(true);
        stamper.close();
        reader.close();
        // add the PDF to PdfCopy
        reader = new PdfReader(baos.toByteArray());
        copy.addDocument(reader);
        reader.close();
    }
    br.close();
    document.close();
}

这是三种情况。您的问题对任何人来说都不清楚,但您可以决定哪种情况最适合您的需求。我建议您在编码之前花时间学习。观看视频,尝试示例,如果您仍有疑问,您可以提出更聪明的问题。

关于java - IText 将文档与 acrofields 合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28566190/

相关文章:

java - 将编码器添加到 Sentry 附加器时出现错误

javascript - 如何处理VBS中的JavaScript错误?

adobe - Adobe XD Windows 用户无法使用蒙版选项吗?

javascript - Adobe Acrobat Pro XI - 将 Javascript 添加到 PDF

.net - 使用 itextsharp 添加图像并跨越多个页面

java - Flying Saucer - 不呈现 html 实体

java - 在java中插入字符串

java - 如何在 LoadRunner SAP GUI 协议(protocol)中添加文本检查以验证 sapgui_status_bar_get_text

java - FlatMap 是一个可迭代对象,并将其组合回可迭代对象

java - iTextPDF 签名 : how to not show signature fields, 但显示图像