PDFBox 2.0 创建签名字段并使用已签名的文档保存增量

PDFBox 2.0 create signature field and save incremental with already signed document

我已阅读 here about how saveIncremental is working, and my final result needs to be something like , 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 无法使用 saveIncremental。我已将以下代码片段(改编)添加到主要功能的末尾,但没有结果:

    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);
}

生成的文件不包含任何签名字段。我尝试将 COSObject.needToBeUpdated(true) 更新为 acroform、signatureField、pddocument、页面、小部件,但没有结果。签名栏只有在我正常保存的时候才会出现

编辑:我设法添加了一个空的签名字段(在 COSObject.needToBeUpdated 链上编辑的代码),但它破坏了现有的签名。

我想念什么?谢谢!

我的实际代码:

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

你的问题更新后剩下的问题是你替换现有的AcroForm定义:

// Add a new AcroForm and add that to the document
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);

改变太多,超出允许范围,超出您的实际需要。

你想要的是 检索 现有的 AcroForm 定义并只标记它及其 Fields 保存条目:

PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
acroForm.getCOSObject().setNeedToBeUpdated(true);
COSObject fields = acroForm.getCOSObject().getCOSObject(COSName.FIELDS);
if (fields != null)
    fields.setNeedToBeUpdated(true);

使用我为您的示例文档获取的代码:

(当然,对于 没有 现有 AcroForm 定义的文档,您可能需要添加一个新定义,因此

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);

可能是完整的变体。)