我在PDF文档中(以编程方式)填写了表格(AcroPdf),然后在文档上签名。我从doc.pdf开始,使用PDFBox的setFields.java示例创建doc_filled.pdf。然后,我根据签名示例使用一些代码对doc_filled.pdf进行签名,以创建doc?filled_signed.pdf,然后在Acrobat Reader中打开pdf。输入的字段数据可见,并且签名面板告诉我
“此签名中包含格式或信息方面的错误(签名字节数组无效)”
到目前为止,我知道:
PDDocument doc = PDDocument.load(new File("doc.pdf"));
doc.save(new File("doc_filled.pdf"));
doc.close();
足以破坏后来应用的签名代码。
另一方面,如果我使用相同的doc.pdf,请在Adobe中手动输入该字段的值,签名代码会产生有效的签名。
我究竟做错了什么?
更新:
@mkl要求我提供文件,我正在谈论(我目前没有足够的声誉,无法将所有文件发布为链接,对于给您带来的不便表示歉意):
通过使用以下方法一次性签名并填写文档来创建最后一个
doc.saveIncremental();
正如我在评论中所写,
setNeedToBeUpdate(true);
不过似乎丢失了。
引用@mkl的第二条评论,我发现了这一点
这样的问题:Saved Text Field value is not displayed properly in PDF generated using PDFBOX,它也覆盖了一些未显示的输入文本。我尝试了一下,申请了
setBoolean(COSName.getPDFName("NeedAppearances"), true);
到字段和表单的字典中,该字典随后显示字段上下文,但是最后没有添加签名。我仍然需要进一步研究。
更新:
故事在这里继续:PDFBox 1.8.10: Fill and Sign Document, Filling again fails
最佳答案
OP原始问题的原因,即在用PDFBox加载PDF(用于表单填充)然后保存它之后,该新PDF无法使用PDFBox签名代码成功签名,已在this answer中进行了详细说明,在短的:
因此,对于具有交叉引用流的OP原始PDF
doc.pdf
:doc_filled.pdf
)doc_filled_signed.pdf
)The answer referenced above还提供了一些解决方法:
通常,我会建议使用后一个选项,因为如果使PDFBox保存例程相互兼容,则前一个选项可能会中断。
但是,遗憾的是,后一种选项要求将添加和更改的对象标记为已更新,包括来自文档目录的路径。如果这不可能或至少太麻烦,则首选第一个选项。
在当前情况下,OP尝试了后一种选项(
doc_filled_and_signed.pdf
):At the Moment the text box's content is only visible, when the text box is selected (with Acrobat reader and Preview the same behaviour). I flag the PDField, all of its parents, the AcroForm, the Catalog as well as the page where it is displayed.
他将更改的字段标记为已更新,但未标记关联的外观流,该外观流在设置表单字段值时由PDFBox自动生成。
因此,在结果PDF文件中,该字段具有新值,但是旧的,空的外观流。仅当单击该字段时,Adobe Reader才会根据要编辑的值创建新外观。
因此,OP还必须标记新的正常外观流(表单字段字典包含引用字典的 AP 条目,其中 N 引用正常外观流)。另外(如果查找更改或添加的条目变得太麻烦了),他可以尝试其他选择。
关于java - PDFBox 1.8.10 : Fill and Sign PDF produces invalid signatures,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32884607/