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

Java 如何使用pdfbox在pdf最后一页的左下角应用数字签名图像?,java,digital-signature,pdfbox,Java,Digital Signature,Pdfbox,标题说明了一切,我能够使用pdfbox 2.0.8版直观地签署pdf。目前,我必须硬编码的图像开始协调的代码。但随着PDF的变化,图像的位置总是需要相应地改变。我想在左角的pdf末尾应用签名图像。我如何在代码中获得该职位?这是我的代码,使用x&y硬编码坐标。在代码中,“签名”是可见的签名对象,“页面”是pdf的最后一页,“args[2]”是要签名的pdf文件: int _x = 30; int _y = 420; signing.setVisibleSignDesigner(args[2], _

标题说明了一切,我能够使用pdfbox 2.0.8版直观地签署pdf。目前,我必须硬编码的图像开始协调的代码。但随着PDF的变化,图像的位置总是需要相应地改变。我想在左角的pdf末尾应用签名图像。我如何在代码中获得该职位?这是我的代码,使用x&y硬编码坐标。在代码中,“签名”是可见的签名对象,“页面”是pdf的最后一页,“args[2]”是要签名的pdf文件:

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);
我想要的签名示例:


编辑:添加图像以澄清我希望签名字段位于文档的末尾,而不是最后一页的末尾。文档可能在最后一页的顶部完成,所以字段也应该在文本的正后方,而不是在页面的末尾。很抱歉,我之前的问题不清楚。

根据问题注释中的说明,您尝试将签名放置在上一文档页面现有内容的边界框下方

要确定该边界框,可以使用中显示的

但是,正如您在回复一条注释时发现的那样,您不能简单地将其结果用作
CreateVisibleSignature.setVisibleSignDesigner的输入,因为假定不同的坐标系:

  • BoundingBoxFinder
    使用相关页面的PDF默认用户空间坐标:它们由相关页面的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);
(测试
signLikeHemantPdfTest

评论 我发现一个文件看起来像你的育空教育PDF测试文件。将上面的代码应用到该文件中,可以观察到最后一行可见文本和图像之间有一个小间隙。此间隙是由“请访问我们的网站”行下方的一行中的一些空格字符造成的。
BoundingBoxFinder
不会检查绘图指令是否最终产生可见的结果,它总是将有问题的区域添加到边界框中

通常,您可能希望从由上述代码计算的y坐标中减去一小点,以在以前的页面内容和新的签名小部件之间创建一个视觉间隙

查看
CreateVisibleSignature
的来源,可以看到实际上y坐标是通过从MediaBox的高度减去而不是从其上边框值减去来转换的。最终,这些坐标被复制到目标文档中。因此,可能需要在上述代码中使用
mediaBox.getHeight()
而不是
mediaBox.getUpperRightY()

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


一般来说,在使用PDFBox时,任意使用不同的坐标系是相当少的刺激源之一。

左下角是(0,0),您尝试过吗?当前PDFBox版本为2.0.17。@TilmanHausherr左下角为(0,0)-目标页面坐标不一定如此。或者
VisibleSignature
VisibleSignDesigner
是否将其正常化?@mkl如果你是指旋转,有一种方法
PDVisibleSignDesigner.adjustForRotation()
是受你的回答启发而产生的。@tilmahausher“如果你是指旋转”-否,我想到的是带有裁剪框的文档页面,裁剪框的左下角没有原点,因此您基本上要查找该页面现有内容的边界框。您可以在中查看如何确定该边界框。只需确定此处解释的边界框,并将签名放在正下方。正如我所说,我只处理简单的PDF,没有任何复杂的内容。这个解决方案对我很有效。谢谢:)