问题
I have read here about how saveIncremental is working, and my final result needs to be something like here , in the way that I have managed to create visible signature with multiple visualization based on the signature field itself (not like in the response, but the response helped me so much). To elaborate the title, my base task for now is to create an empty signature field on an already signed document without braking the existing signature. However, the example here is not working with saveIncremental. I have added the following snippet (adapted) to the end of the main function, but without result:
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
// ...
COSDictionary pageTreeObject = pdPage.getCOSObject();
while (pageTreeObject != null) {
pageTreeObject.setNeedToBeUpdated(true);
pageTreeObject = (COSDictionary) pageTreeObject.getDictionaryObject(COSName.PARENT);
}
The resulting file does not contain any signature field. I have tried to update COSObject.needToBeUpdated(true) to acroform, signatureField, pddocument, page, widget, without result. The signature field only appears when I normally Save.
EDIT: I have managed to add an empty signature field (code edited on the COSObject.needToBeUpdated chain), but it breaks the existing signature.
What do I miss? Thanks!
My actual code:
public class CreateEmptySignatureForm {
public static void main(String[] args) throws IOException
{
InputStream resource = new FileInputStream("test-semnat.pdf");
PDDocument document = PDDocument.load(resource);
PDPage page = document.getPage(0);
// Add a new AcroForm and add that to the document
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
// Create empty signature field, it will get the name "Signature1"
PDSignatureField signatureField = new PDSignatureField(acroForm);
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
PDRectangle rect = new PDRectangle(50, 250, 200, 50);
widget.setRectangle(rect);
widget.getCOSObject().setNeedToBeUpdated(true);
widget.setPage(page);
page.getAnnotations().add(widget);
page.getCOSObject().setNeedToBeUpdated(true);
acroForm.getFields().add(signatureField);
// general updates
document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
OutputStream os = new FileOutputStream("fooo.pdf");
document.saveIncremental(os);
System.out.println("done");
}
}
test-semnat.pdf
回答1:
The remaining problem after your question update is that you replace the existing AcroForm definition:
// Add a new AcroForm and add that to the document
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
That changes too much, more than allowed and more than you actually want.
What you want is to retrieve the existing AcroForm definition and only mark it and its Fields entry for saving:
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
acroForm.getCOSObject().setNeedToBeUpdated(true);
COSObject fields = acroForm.getCOSObject().getCOSObject(COSName.FIELDS);
if (fields != null)
fields.setNeedToBeUpdated(true);
With that code I get for your example document:
(Of course, for documents without an existing AcroForm definition you will probably want to add a new one, so
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
if (acroForm == null) {
acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
}
acroForm.getCOSObject().setNeedToBeUpdated(true);
COSObject fields = acroForm.getCOSObject().getCOSObject(COSName.FIELDS);
if (fields != null)
fields.setNeedToBeUpdated(true);
is probably the complete variant.)
来源:https://stackoverflow.com/questions/62601879/pdfbox-2-0-create-signature-field-and-save-incremental-with-already-signed-docum