pdfbox - 如何增量签署更新的文档或更改
pdfbox - How to incrementally sign updated document or changes
我有一些关于 pdfbox 的问题。
- 我想连续签署一份可能会发生变化的文件,例如a) originalPdf(由 X 签名),b)将图像添加到 pdf(然后由 Y 签名)等,这样签名都是有效的。如果可能的话,我怎样才能用 pdfbox 达到这个目的?我尝试了几种方法(例如使用 saveIncremental),但它们没有给出预期的结果。
- 或者我是否需要预先定义空字段并允许用图像更新它们以使签名有效?这是用注解实现的吗,如果是,我们如何实现?
public 域中的任何有用提示或代码参考都将非常有帮助。谢谢
....
contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
PDImageXObject pdImage = PDImageXObject.createFromFile("C:/logo.png", doc);
....
page.getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT).setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
page.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
doc.saveIncremental(fos);
只允许对签名文档进行少量更改,有关详细信息,请参阅here。所以确实,签名后不能更改页面内容,能不能填表,甚至能不能任意注解,要看原签名的签名类型。
如果签名确实允许添加注释,即如果只有批准(非认证)签名或最多有一个带有注释、表单填写和的认证签名允许数字签名,您可以在注释中添加图片。
使用 PDFBox,您可以在增量更新中添加显示图像的注释,如下所示:
PDDocument document = ...;
PDImageXObject image = ...;
OutputStream result = ...;
PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
appearanceStream.setBBox(new PDRectangle(1, 1));
appearanceStream.setResources(new PDResources());
try ( PDPageContentStream contentStream = new PDPageContentStream(document, appearanceStream) ) {
contentStream.drawImage(image, new Matrix());
}
PDAppearanceDictionary appearance = new PDAppearanceDictionary();
appearance.setNormalAppearance(appearanceStream);
PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
stamp.setLocked(true);
stamp.setLockedContents(true);
stamp.setPrinted(true);
stamp.setReadOnly(true);
stamp.setAppearance(appearance);
stamp.setIntent("StampImage");
stamp.setRectangle(new PDRectangle(200, 500, 100, 100));
PDPage page = document.getPage(0);
page.getAnnotations().add(stamp);
Set<COSDictionary> objectsToWrite = new HashSet<>();
objectsToWrite.add(page.getCOSObject());
document.saveIncremental(result, objectsToWrite);
(AddToSignedFile 测试 testAddImageAnnotation
)
我在这里使用了 3.0.0 的开发头中可用的功能,saveIncremental
重载带有第二个参数,该参数接受要保存的字典集合。如果您使用的是早期版本,则可能必须使用 setNeedToBeUpdated
.
标记从文档目录到页面对象的对象路径以包含在增量更新中
如果签名不允许添加注释,但允许表单编辑,即如果有认证签名允许填写表单和数字签名,你至少可以填写表单域。这尤其可能包括将按钮的外观设置为您选择的图像,因为 Adobe 经常将按钮误用作伪图像字段。这当然意味着您需要为每个需要的后续添加准备一个字段。
如果签名甚至不允许这样做,即如果有认证签名不允许更改,或者如果没有可供您添加的开放表单字段,你真倒霉。
顺便说一句,自 PDF 2.0 以来,还可以通过批准签名的签名锁定字典中的条目使认证级别更加严格。在上述情况下,您可能需要考虑这一点...
我有一些关于 pdfbox 的问题。
- 我想连续签署一份可能会发生变化的文件,例如a) originalPdf(由 X 签名),b)将图像添加到 pdf(然后由 Y 签名)等,这样签名都是有效的。如果可能的话,我怎样才能用 pdfbox 达到这个目的?我尝试了几种方法(例如使用 saveIncremental),但它们没有给出预期的结果。
- 或者我是否需要预先定义空字段并允许用图像更新它们以使签名有效?这是用注解实现的吗,如果是,我们如何实现?
public 域中的任何有用提示或代码参考都将非常有帮助。谢谢
....
contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true);
PDImageXObject pdImage = PDImageXObject.createFromFile("C:/logo.png", doc);
....
page.getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT).setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
page.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
doc.saveIncremental(fos);
只允许对签名文档进行少量更改,有关详细信息,请参阅here。所以确实,签名后不能更改页面内容,能不能填表,甚至能不能任意注解,要看原签名的签名类型。
如果签名确实允许添加注释,即如果只有批准(非认证)签名或最多有一个带有注释、表单填写和的认证签名允许数字签名,您可以在注释中添加图片。
使用 PDFBox,您可以在增量更新中添加显示图像的注释,如下所示:
PDDocument document = ...;
PDImageXObject image = ...;
OutputStream result = ...;
PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
appearanceStream.setBBox(new PDRectangle(1, 1));
appearanceStream.setResources(new PDResources());
try ( PDPageContentStream contentStream = new PDPageContentStream(document, appearanceStream) ) {
contentStream.drawImage(image, new Matrix());
}
PDAppearanceDictionary appearance = new PDAppearanceDictionary();
appearance.setNormalAppearance(appearanceStream);
PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
stamp.setLocked(true);
stamp.setLockedContents(true);
stamp.setPrinted(true);
stamp.setReadOnly(true);
stamp.setAppearance(appearance);
stamp.setIntent("StampImage");
stamp.setRectangle(new PDRectangle(200, 500, 100, 100));
PDPage page = document.getPage(0);
page.getAnnotations().add(stamp);
Set<COSDictionary> objectsToWrite = new HashSet<>();
objectsToWrite.add(page.getCOSObject());
document.saveIncremental(result, objectsToWrite);
(AddToSignedFile 测试 testAddImageAnnotation
)
我在这里使用了 3.0.0 的开发头中可用的功能,saveIncremental
重载带有第二个参数,该参数接受要保存的字典集合。如果您使用的是早期版本,则可能必须使用 setNeedToBeUpdated
.
如果签名不允许添加注释,但允许表单编辑,即如果有认证签名允许填写表单和数字签名,你至少可以填写表单域。这尤其可能包括将按钮的外观设置为您选择的图像,因为 Adobe 经常将按钮误用作伪图像字段。这当然意味着您需要为每个需要的后续添加准备一个字段。
如果签名甚至不允许这样做,即如果有认证签名不允许更改,或者如果没有可供您添加的开放表单字段,你真倒霉。
顺便说一句,自 PDF 2.0 以来,还可以通过批准签名的签名锁定字典中的条目使认证级别更加严格。在上述情况下,您可能需要考虑这一点...