IText 将文档与 acrofields 合并
IText merge documents with acrofields
我目前有一个 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 合并在一起?
根据您的具体需求,可能会出现不同的情况,但无论如何:您做错了。您应该使用 PdfCopy
或 PdfSmartCopy
来合并文档。
下面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();
}
这是三种情况。您的问题对任何人来说都不清楚,但您可以决定哪种情况最适合您的需求。我建议您在编码之前花时间学习。观看视频,尝试示例,如果您仍然有疑问,您将能够 post 一个更聪明的问题。
我目前有一个 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 合并在一起?
根据您的具体需求,可能会出现不同的情况,但无论如何:您做错了。您应该使用 PdfCopy
或 PdfSmartCopy
来合并文档。
下面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();
}
这是三种情况。您的问题对任何人来说都不清楚,但您可以决定哪种情况最适合您的需求。我建议您在编码之前花时间学习。观看视频,尝试示例,如果您仍然有疑问,您将能够 post 一个更聪明的问题。