根据 iText 8 版本从 iText 5.5 迁移。
我们无法使用新的 iText 8 代码从 pdf 中提取标签,但可以使用旧的 iText 5.5 代码提取标签。
下面是获取标签的代码。
根据新代码
PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(pdfDocument, true);
or
PdfAcroForm pdfAcroForm = PdfFormCreator.getAcroForm(pdfDocument, true);
Map<String, PdfFormField> formFieldMap = pdfAcroForm.getAllFormFields();
按照旧代码
reader = new com.itextpdf.text.pdf.PdfReader(docdByteArray);
PdfStamper stamper = new PdfStamper(reader, baos);
AcroFields acroFields = stamper.getAcroFields();
我们还尝试了 Apache PDBox,但我们得到了与使用新 iText 8 相同的结果。
仅 1 或 2 个 pdf 会出现此问题。我们有另一个 pdf,其中也有相同的标签,并且我们可以使用新旧代码提取该标签。
我们能够从原始模板中提取该标签,但在预填充后我们失败了。
就我而言,是 pdf 文件损坏还是字段结构受到干扰或任何其他问题。
无法附加 pdf 文档,因为它是机密文档。
我们期望使用 iText 5.5 版本从原始 pdf 和预填充 pdf 获得相同的结果。
iText5 和 8 在处理 acroform 字段方面的主要区别在于
另请注意,小部件注释字典可能包含表单字段的数据。
所以区别就在这里,如果您的注释仅出现在页面上,并且没有以任何方式在 acro 表单字典中引用(既不是直接在字段数组中,也不是作为任何字段的子项),iText 8 不会将其视为表单字段相关注释(按照pdf规范)并且不会返回。
您可以尝试自己捕获它并添加到 acro 表单中,从而修复文档。代码如下:
private Map<String, PdfFormField> populateFields(PdfDocument doc) {
Map<String, PdfFormField> fields = new HashMap<>();
for (int i = 1; i <= doc.getNumberOfPages(); ++i) {
PdfPage page = doc.getPage(i);
List<PdfAnnotation> annotations = page.getAnnotations();
for (PdfAnnotation annot : annotations) {
if (!annot.getSubtype().equals(PdfName.Widget)) {
continue;
}
PdfFormField field = PdfFormField.makeFormField(annot.getPdfObject(), doc);
if (field != null) {
fields.put(field.getFieldName().toUnicodeString(), field);
}
}
}
return fields;
}
请注意,此代码不考虑 acro 表单字段层次结构,仅考虑可能会或可能不会从 acro 表单引用的小部件注释的简单列表。 因此,如果您发现此方法返回的字段映射中与 PdfAcroForm.getAllFormFields() 相比有任何独特之处,您可以使用 PdfAcroForm.addField 将其添加到 acro 表单中。