IText将文档与acrofields合并

时间:2015-02-17 16:28:23

标签: 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();

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

1 个答案:

答案 0 :(得分:4)

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

以下video tutorial解释了不同的方案。

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

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

如果要合并不同的表单而不展平它们,则应使用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()并制作确保我们不会忘记使用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(); } 方法,或者不会复制字段。

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

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

我们来看看MergeForms示例:

renameFields()

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

合并展平形式

MergeForms2中,我们使用PdfCopy填写表单。结果是一个PDF文件保存在内存中,并使用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(); } 合并。如果您合并不同的表单,这个示例很好,这实际上是如何不执行的示例(如FillFlattenMerge1中所述)。

video tutorial显示了如何合并正确填写和展平的相同表单:

{{1}}

这是三种情况。您的问题对于任何人来说都不太清楚,但您要确定哪种方案最适合您的需求。我建议你在编码前花时间学习。观看视频,尝试示例,如果您仍有疑问,您将能够发布更智能的问题。