用例:我正在开发一项功能,该功能需要将图像附加到 PDF,而不会使预先存在的数字签名失效。 PDF 应该有一个指定用于图像附件的表单字段,可以稍后填充。我想使用 PDFBox 来实现这个。
实现:由于 PDF 缺乏专用的图像表单字段,我使用 PDPushButton 作为解决方法,遵循这些资源中概述的方法;
此外,PDF 还包含签名表单字段。该过程包括首先对签名字段进行签名,然后将图像附加到 PDPushButton 字段。然而,这个序列导致签名无效。
这是将图像附加到 PDPushButton 的代码。
@SneakyThrows
public static void fillInitialField(String inputFilePath, String outputFilePath) {
// Load input file
PDDocument document = PDDocument.load(new File(inputFilePath));
// Find and link the relevant signature field
PDPushButton initial = PdfService.findInitial(document, "132323423180965");
PDImageXObject pdImageXObject = PDImageXObject.createFromFile("initial.png", document);
float width = 10 * pdImageXObject.getWidth();
float height = 10 * pdImageXObject.getHeight();
PDAppearanceStream pdAppearanceStream = new PDAppearanceStream(document);
pdAppearanceStream.setResources(new PDResources());
try (PDPageContentStream pdPageContentStream = new PDPageContentStream(document, pdAppearanceStream)) {
pdPageContentStream.drawImage(pdImageXObject, 200, 300, width, height);
}
pdAppearanceStream.setBBox(new PDRectangle(width, height));
List<PDAnnotationWidget> widgets = initial.getWidgets();
for (PDAnnotationWidget pdAnnotationWidget : widgets) {
PDAppearanceDictionary pdAppearanceDictionary = pdAnnotationWidget.getAppearance();
if (pdAppearanceDictionary == null) {
pdAppearanceDictionary = new PDAppearanceDictionary();
pdAnnotationWidget.setAppearance(pdAppearanceDictionary);
}
pdAppearanceDictionary.setNormalAppearance(pdAppearanceStream);
}
initial.setReadOnly(true);
// Save and close the document
FileOutputStream fos = new FileOutputStream(outputFilePath);
document.save(fos);
document.close();
}
我创建了一个复制此问题的存储库,可以在此处找到:https://github.com/ContractSPAN/ImageFormFieldIssue
如何在 PDF 表单字段中实现图像附件,且不会使现有签名失效?我对实现此功能的替代方法持开放态度。
您在
save
结束时执行常规的fillInitialField
。常规保存将重新排列和更改有符号字节范围。因此,您需要像在 saveIncremental
末尾那样执行 sign
。
请注意,pdfbox 2 中的
saveIncremental
要求您标记 (setNeedToBeUpdated(true)
) 所有已更改的对象,包括从预告片分别通向它们的一系列对象。在签名的情况下,很多标记已经由 PDFBox 本身完成。但在您的 fillInitialField
方法中,您必须自己完成所有标记。