[英]How to insert image programmatically in to AcroForm field using java PDFBox?
[英]Does PDFBox allow to remove one field from AcroForm?
我正在使用Apache PDFBox 2.0.8,並嘗試刪除一個字段。 但是找不到方法,就像我可以使用iText一樣: PdfStamper.getAcroFields().removeField("signature3")
。
我想做的事。 最初,我有帶有3個數字簽名的PDF模板。 在某些情況下,我只需要2個簽名,因此在這種情況下,我需要從模板中刪除第3個簽名。 似乎我無法用PDFBox做到這一點,我發現關閉的東西正在使該字段扁平化,但是問題是,如果扁平化的特定PDField(不是整個表單,而是一個字段)-所有其他簽名都失去了它們的功能,看起來就像他們也變得扁平一樣。 這是執行此操作的代碼:
PDDocument document = PDDocument.load(file);
PDDocumentCatalog documentCatalog = document.getDocumentCatalog();
PDAcroForm acroForm = documentCatalog.getAcroForm();
List<PDField> flattenList = new ArrayList<>();
for (PDField field : acroForm.getFieldTree()) {
if (field instanceof PDSignatureField && "signature3".equals(field.getFullyQualifiedName())) {
flattenList.add(field);
}
}
acroForm.flatten(flattenList, true);
document.save(dest);
document.close();
正如Tilman在評論中已經提到的那樣, PDFBox沒有從字段樹中刪除字段的方法。 盡管如此,它仍然具有操縱底層PDF結構的方法,因此人們可以自己編寫這樣的方法,例如:
PDField removeField(PDDocument document, String fullFieldName) throws IOException {
PDDocumentCatalog documentCatalog = document.getDocumentCatalog();
PDAcroForm acroForm = documentCatalog.getAcroForm();
if (acroForm == null) {
System.out.println("No form defined.");
return null;
}
PDField targetField = null;
for (PDField field : acroForm.getFieldTree()) {
if (fullFieldName.equals(field.getFullyQualifiedName())) {
targetField = field;
break;
}
}
if (targetField == null) {
System.out.println("Form does not contain field with given name.");
return null;
}
PDNonTerminalField parentField = targetField.getParent();
if (parentField != null) {
List<PDField> childFields = parentField.getChildren();
boolean removed = false;
for (PDField field : childFields)
{
if (field.getCOSObject().equals(targetField.getCOSObject())) {
removed = childFields.remove(field);
parentField.setChildren(childFields);
break;
}
}
if (!removed)
System.out.println("Inconsistent form definition: Parent field does not reference the target field.");
} else {
List<PDField> rootFields = acroForm.getFields();
boolean removed = false;
for (PDField field : rootFields)
{
if (field.getCOSObject().equals(targetField.getCOSObject())) {
removed = rootFields.remove(field);
break;
}
}
if (!removed)
System.out.println("Inconsistent form definition: Root fields do not include the target field.");
}
removeWidgets(targetField);
return targetField;
}
void removeWidgets(PDField targetField) throws IOException {
if (targetField instanceof PDTerminalField) {
List<PDAnnotationWidget> widgets = ((PDTerminalField)targetField).getWidgets();
for (PDAnnotationWidget widget : widgets) {
PDPage page = widget.getPage();
if (page != null) {
List<PDAnnotation> annotations = page.getAnnotations();
boolean removed = false;
for (PDAnnotation annotation : annotations) {
if (annotation.getCOSObject().equals(widget.getCOSObject()))
{
removed = annotations.remove(annotation);
break;
}
}
if (!removed)
System.out.println("Inconsistent annotation definition: Page annotations do not include the target widget.");
} else {
System.out.println("Widget annotation does not have an associated page; cannot remove widget.");
// TODO: In this case iterate all pages and try to find and remove widget in all of them
}
}
} else if (targetField instanceof PDNonTerminalField) {
List<PDField> childFields = ((PDNonTerminalField)targetField).getChildren();
for (PDField field : childFields)
removeWidgets(field);
} else {
System.out.println("Target field is neither terminal nor non-terminal; cannot remove widgets.");
}
}
( RemoveField輔助方法removeField
和removeWidgets
)
可以這樣將其應用於文檔和字段:
PDDocument document = PDDocument.load(SOURCE_PDF);
PDField field = removeField(document, "Signature1");
Assert.assertNotNull("Field not found", field);
document.save(TARGET_PDF);
document.close();
( RemoveField測試testRemoveInvisibleSignature
)
PS:我不確定PDFBox實際在某處緩存了多少與表格相關的信息。 因此,我建議至少在沒有測試的情況下,不要在同一文檔操作會話中進一步操作表單信息。
PPS:您可以在removeWidgets
幫助器方法中找到一個TODO。 如果該方法輸出“窗口小部件注釋沒有關聯的頁面;無法刪除窗口小部件” ,則必須添加缺少的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.