如何使用pdfbox在pdf最后一页的左下角应用数字签名图像?

How to apply digital signature image at bottom left position in the last page of pdf using pdfbox?

标题说明了一切,我可以使用 pdfbox 2.0.8 版直观地签署 pdf。目前我必须 hard-code 在代码中开始协调图像。但随着 PDF 的变化,图像的位置总是需要相应地改变。我想在左下角的 pdf 末尾应用签名图像。我如何在代码中获得该位置?这是我的代码,使用 _x & _y 硬编码坐标。代码中'signing'是可见签名object和'page'是pdf的最后一页,'args[2]'是pdf-file待签名:

int _x = 30;
int _y = 420;
signing.setVisibleSignDesigner(args[2], _x, _y, -50, imageStream, page);
imageStream.close();
signing.setExternalSigning(externalSig);
signing.signPDF(documentFile, signedDocumentFile, tsaClient);
removeFile(imageResult);

我想要的签名示例:

编辑:添加图片以阐明我希望签名字段位于文档末尾,而不是最后一页的末尾。文档可能在最后一页的顶部完成,因此字段也应该紧跟在文本之后,而不是在页面末尾。抱歉,我之前的问题不清楚。

根据问题评论中的说明,您尝试将签名放在最后一页文档现有内容的边界框下方。

要确定边界框,您可以使用 BoundingBoxFinder presented in

但是正如您在回复对此效果的评论时发现的那样,您不能简单地将其结果用作 CreateVisibleSignature.setVisibleSignDesigner 的输入,因为假设有不同的坐标系:

  • BoundingBoxFinder 使用相关页面的 PDF 默认用户 space 坐标:它们由相关页面的 MediaBox 给出,并且使它们的 y 坐标向上增加。通常原点在页面的左下角。
  • 另一方面,
  • CreateVisibleSignature 使用具有相同单位长度但原点在页面左上角且 y 坐标递增的坐标系向下。

因此,必须转换坐标,例如像这样:

File documentFile = new File(SOURCE);
File signedDocumentFile = new File(RESULT);

Rectangle2D boundingBox;
PDRectangle mediaBox;
try (   PDDocument document = PDDocument.load(documentFile) ) {
    PDPage pdPage = document.getPage(0);
    BoundingBoxFinder boundingBoxFinder = new BoundingBoxFinder(pdPage);
    boundingBoxFinder.processPage(pdPage);
    boundingBox = boundingBoxFinder.getBoundingBox();
    mediaBox = pdPage.getMediaBox();
}

CreateVisibleSignature signing = new CreateVisibleSignature(ks, PASSWORD.clone());
try (   InputStream imageStream = IMAGE_STREAM) {
    signing.setVisibleSignDesigner(documentFile.getPath(), (int)boundingBox.getX(), (int)(mediaBox.getUpperRightY() - boundingBox.getY()), -50, imageStream, 1);
}
signing.setVisibleSignatureProperties("name", "location", "Security", 0, 1, true);
signing.setExternalSigning(false);
signing.signPDF(documentFile, signedDocumentFile, null);

(CreateSignature 测试 signLikeHemantPdfTest)

备注

我找到了一份看起来像您的育空教育 PDF 测试文件的文档 here。将上面的代码应用于该文件,可以观察到最后一行可见文本和图像之间有一个小间隙。此间隙是由“请访问我们的网站”行下方一行中的一些 space 个字符引起的。 BoundingBoxFinder 不检查绘图指令是否最终导致可见的东西,它总是将有问题的区域添加到边界框。

一般来说,您可能希望从上面代码计算的 y 坐标中减去一小部分,以便在以前的页面内容和新的签名小部件之间创建一个视觉间隙。

查看 CreateVisibleSignature 的来源发现实际上 y 坐标是通过从 height[=68 中减去它们来转换的=] 的 MediaBox,而不是来自其 上边框值 。最终这些坐标被复制到目标文档中。因此,可能有必要在上面的代码中使用 mediaBox.getHeight() 而不是 mediaBox.getUpperRightY()

查看 CreateVisibleSignature2 的来源发现实际上使用了 CropBox 而不是 MediaBox。如果您的代码源自该示例,则可能需要将上面代码中的 pdPage.getMediaBox() 替换为 pdPage.getCropBox()

一般来说,这种任意使用不同坐标系是使用 PDFBox 时为数不多的恼人原因之一。