javaspring-bootpdfitextpdfbox

PDFBox acroform unable to find fields previously added, on an iText signed pdf


i have a pdf that has a couple of signatures added using iText : iText signed file

I am using PDFBox(version 3.0.4) to add more signature fields into the same PDF using createEmptySignature() with fieldname asb_191025_0(and more) then save it using doc.saveIncremental(). Using inspectFields() i can see that the fields have been added. (inspectFields() is basically printFields() from github sample)

This is the updated/ saved file.

After that, i open the same file to place signature into the fields. However inspectFields() only returns the 2 iText signed fields and not the newly added ones. Calling acroForm.getField("asb_191025_0") returns null as well.

Opening the file in both Acrobat and notepad++ do show all the fields.

This only happens when I put new fields into an iText signed pdf. Theres no problem if i start with a clean pdf.

What did I miss?

Thank you.

    public static void createEmptySignature(PDDocument doc, int pageIndex, PDRectangle rect, String fieldName) throws Exception {
        PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
        if (acroForm == null) {
            acroForm = new PDAcroForm(doc);
            doc.getDocumentCatalog().setAcroForm(acroForm);
        }
        
        if(acroForm.getFields() instanceof AbstractList){
            acroForm.setFields(new ArrayList<>());
        }
        
        inspectFields(acroForm);

        PDSignatureField signatureField = new PDSignatureField(acroForm);
        signatureField.setPartialName(fieldName);
        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        widget.setRectangle(rect);
        widget.setPage(doc.getPage(pageIndex));
        widget.setPrinted(true);

        doc.getPage(pageIndex).getAnnotations().add(widget);

        acroForm.getFields().add(signatureField);
    }

Solution

  • You say you use doc.saveIncremental(). The JavaDocs of that method start with:

    /**
     * Save the PDF as an incremental update. This is only possible if the PDF was loaded from a file or a stream, not
     * if the document was created in PDFBox itself. There must be a path of objects that have
     * {@link COSUpdateInfo#isNeedToBeUpdated()} set, starting from the document catalog. For signatures this is taken
     * care by PDFBox itself.
    

    I don't see you setting NeedToBeUpdated at all. Thus, it is pure luck that any of your changes make it into the result document at all.

    So to be sure your changes are saved incrementally, make sure all your changes are reachable from the catalog via chains of objects all having isNeedToBeUpdated set.


    In PDFBox v3 there is an overload of saveIncremental that doesn't require such chains but requires you to collect the indirect dictionaries themselves.