Java IText将文档与字段合并

Java IText将文档与字段合并,java,adobe,itext,Java,Adobe,Itext,我目前有一个PdfReader和一个PdfStamper,我正在用它们填写acrofields。我现在必须将另一个pdf复制到我一直填写的表格的末尾,当我这样做时,我会丢失我复制的新表格上的acrofield。这是代码 public static void addSectionThirteenPdf(PdfStamper stamper, Rectangle pageSize, int pageIndex){ PdfReader reader = new PdfReader(Faces

我目前有一个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();

有没有一种方法可以使用第一段代码合并,并将两个字段合并在一起?

根据您的具体需要,可能会出现不同的情况,但无论如何:您做得不对。您应该使用
PdfCopy
PdfSmartCopy
合并文档

下面将解释不同的场景

您可以在中找到大多数示例

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

如果要在不展平的情况下合并不同的表单,应使用
PdfCopy
,如示例所示:

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

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

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

让我们来看一个例子:


这是三种情况。你的问题太不清楚了,除了你之外,任何人都无法决定哪种情况最适合你的需要。我建议您在编写代码之前花点时间学习。观看视频,尝试示例,如果您仍然有疑问,您可以发布一个更聪明的问题。

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

下面将解释不同的场景

您可以在中找到大多数示例

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

如果要在不展平的情况下合并不同的表单,应使用
PdfCopy
,如示例所示:

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

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

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

让我们来看一个例子:


这是三种情况。你的问题太不清楚了,除了你之外,任何人都无法决定哪种情况最适合你的需要。我建议您在编写代码之前花点时间学习。观看视频,尝试示例,如果您仍然有疑问,您可以发布一个更聪明的问题。

copy.setMergeFields();在我的PdfCopy中不存在,我已经查找了这些解决方案。我正在使用com.itextpdf itextpdf 5.0.6我想看看它是否过时了,因为它现在已经过时了。iText 5.0.6的日期是2011年2月4日,也就是4年前!哈哈哈,是的,我一开始看就注意到了哈哈。我要看看我是否能让它与这个新代码一起工作:)。我一测试就告诉你!非常有帮助!尽管我希望有一种方法可以通过使用stamper.insertPage或类似的东西来复制acrofields。谢谢你的帮助!copy.setMergeFields();在我的PdfCopy中不存在,我已经查找了这些解决方案。我正在使用com.itextpdf itextpdf 5.0.6我想看看它是否过时了,因为它现在已经过时了。iText 5.0.6的日期是2011年2月4日,也就是4年前!哈哈哈,是的,我一开始看就注意到了哈哈。我要看看我是否能让它与这个新代码一起工作:)。我一测试就告诉你!非常有帮助!尽管我希望有一种方法可以通过使用stamper.insertPage或类似的东西来复制acrofields。谢谢你的帮助!
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();
    }
}
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();
}
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();
}