如何使用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 时为数不多的恼人原因之一。
标题说明了一切,我可以使用 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 时为数不多的恼人原因之一。