当前位置: 首页 > 知识库问答 >
问题:

如何使用iText将签名附加到pdf?

伍捷
2023-03-14

我在实现中适用于简单情况,但不适用于复杂情况。原始 pdf 将显示在中央窗格中。我有一个侧窗格,其中有一些矩形,如“名称”,“签名”,“时间戳”,可以在pdf上拖动。使用 j 查询可拖动

我知道图像以像素为单位,而PDF尺寸以点为单位。因此,我将以像素为单位的图像坐标转换为点(0.75)。还考虑到,对于图像,原点是在左上
角,而在pdf中,原点是左下角,对于图像,y轴是南区,但对于pdf y轴是北区。

如何着手呢?

编辑:

下面是代码:DocumentField是一个POJO,它具有签名坐标的属性

public void writeDocumentFields(List<DocumentField> documentField,File file, File outputFile) throws IOException    {
    try {
        PdfReader pdfReader = new PdfReader(file.getAbsolutePath());
        PdfReader.unethicalreading=true;
        PdfStamper pdfStamper = new PdfStamper(pdfReader,new FileOutputStream(outputFile));
        for(DocumentField df:documentField){
            int pageNumber = df.getPageNumber()+1;
            PdfContentByte content = pdfStamper.getOverContent(pageNumber);
            Rectangle cropBox = pdfReader.getCropBox(pageNumber);
            if(pdfReader.getPageRotation(pageNumber) > 0) {
                float width = cropBox.getRight();
                cropBox.setRight(cropBox.getHeight());
                cropBox.setTop(width);                   
            }

            if(df.getFieldType().equals("image")){
                df.setxPosition(
                    Float.parseFloat(df.getLeft())*
                    CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
                df.setyPosition(Float.parseFloat(df.getTop())*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
                float x = cropBox.getLeft()  + df.getxPosition();
                float y = cropBox.getTop()  - df.getyPosition();
                Image image = Image.getInstance(df.getFieldValue());
                image.scaleToFit(150*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT, 50*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
                image.setAbsolutePosition(x, y - 36f);
                content.addImage(image);
            }else if(df.getFieldType().equals("checkbox")){
                //...
            }else{
                //...
            }
        }
        pdfStamper.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    }
}   

两种风景的PDF

混合pdf的另一个示例

第 2 次编辑

第二个示例pdf有3页,尺寸为第一页682.04 x 297.12,第二页610.52 x 788.6,第三页几乎与第二页611 x 789.08相同。首先,我尝试将签名放在每页的左上角。这成功了。然后我试着把签名放在每页的左下角。这没有成功。我正在存储拖动到数据库的图像的坐标

第三次编辑jQuery代码捕获可拖放签名小部件的拖放点坐标,如下所示:

 $(".drop").droppable({
      accept: '.dragSigners',
      activeClass: "drop-area",

      drop: function(e, ui) {
        var off = $(this).offset();
        leftPosition  = ui.offset.left - off.left;
        topPosition   = ui.offset.top - off.top;
      }
 });

共有1个答案

冯野
2023-03-14

我试图像这样重现这个问题:

float CONVERSION_FACTOR_FROM_PIXEL_TO_POINT = 0.75f;
List<DocumentField> documentField = new ArrayList<>();

try (   InputStream resource = getClass().getResourceAsStream("Mix PDF.pdf");
        InputStream imageResource = getClass().getResourceAsStream("Signature.png") ) {
    byte[] imageBytes = StreamUtil.inputStreamToArray(imageResource);
    documentField.add(new DocumentField(0, "70", "600", "image", imageBytes));
    documentField.add(new DocumentField(1, "70", "600", "image", imageBytes));
    documentField.add(new DocumentField(2, "70", "600", "image", imageBytes));
    documentField.add(new DocumentField(3, "70", "600", "image", imageBytes));
    documentField.add(new DocumentField(4, "70", "600", "image", imageBytes));

    PdfReader pdfReader = new PdfReader(resource);
    PdfReader.unethicalreading=true;
    PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(new File(RESULT_FOLDER, "StampImagesLikeSubhenduMahanta.pdf")));
    for(DocumentField df:documentField){
        int pageNumber = df.getPageNumber()+1;
        PdfContentByte content = pdfStamper.getOverContent(pageNumber);
        Rectangle cropBox = pdfReader.getCropBox(pageNumber);
        if(pdfReader.getPageRotation(pageNumber) > 0) {
            float width = cropBox.getRight();
            cropBox.setRight(cropBox.getHeight());
            cropBox.setTop(width);                   
        }

        if(df.getFieldType().equals("image")){
            df.setxPosition(
                Float.parseFloat(df.getLeft())*
                CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
            df.setyPosition(Float.parseFloat(df.getTop())*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
            float x = cropBox.getLeft()  + df.getxPosition();
            float y = cropBox.getTop()  - df.getyPosition();
            Image image = Image.getInstance(df.getFieldValue());
            image.scaleToFit(150*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT, 50*CONVERSION_FACTOR_FROM_PIXEL_TO_POINT);
            image.setAbsolutePosition(x, y - 36f);
            content.addImage(image);
        }else if(df.getFieldType().equals("checkbox")){
            //...
        }else{
            //...
        }
    }
    pdfStamper.close(); 
}

(StampImages测试StampImagesLikeSubhenduMahanta)

有了这个POJO类

class DocumentField {
    DocumentField(int pageNumber, String left, String top, String fieldType, byte[] fieldValue) {
        this.pageNumber = pageNumber;
        this.left = left;
        this.top = top;
        this.fieldType = fieldType;
        this.fieldValue = fieldValue;
    }

    int getPageNumber()                 {   return pageNumber;          }
    final int pageNumber;
    String getLeft()                    {   return left;                }
    final String left;
    String getTop()                     {   return top;                 }
    final String top;
    String getFieldType()               {   return fieldType;           }
    final String fieldType;
    byte[] getFieldValue()              {   return fieldValue;          }
    final byte[] fieldValue;
    float getxPosition()                {   return xPosition;           }
    void setxPosition(float xPosition)  {   this.xPosition = xPosition; }
    float xPosition = 0;
    float getyPosition()                {   return yPosition;           }
    void setyPosition(float yPosition)  {   this.yPosition = yPosition; }
    float yPosition = 0;
}

(StampImages助手类)

你在评论中说:

我在所有5页的同一个地方签名。

因此,我对所有DocumentField实例使用了左值70和顶值600

documentField.add(new DocumentField(0, "70", "600", "image", imageBytes));
documentField.add(new DocumentField(1, "70", "600", "image", imageBytes));
documentField.add(new DocumentField(2, "70", "600", "image", imageBytes));
documentField.add(new DocumentField(3, "70", "600", "image", imageBytes));
documentField.add(new DocumentField(4, "70", "600", "image", imageBytes));

但是结果看起来是这样的:

如你所见,签名图像是人们期望的地方。

因此,我无法重现您的问题。

您应该检查所有DocumentField实例的值并检查它们的正确性。

第二个示例pdf有3页,尺寸为第一页682.04 x 297.12,第二页610.52 x 788.6,第三页几乎与第二页611 X 789.08相同。[…]

然后,我尝试将签名放在每页的左下角。这没有成功。我正在存储拖动到数据库的图像的坐标

现在第一页的签名嵌入在正确的位置。但是对于第二页

考虑到第二页和第三页的高度是第一页的两倍多,在所有页面(第1页:约350页,第2页:约3500页,第3页:约300页)上使用大致相同的数据库y(从可见页面顶部开始的像素字段顶部y)值可能会产生完全不同的视觉效果:这些数据库值显然会将签名放在第二页和第三页的中间高度。

所以数据库中的值毫无意义。请检查生成和存储这些坐标的过程。

 类似资料:
  • 我正在尝试数字签名pdf文档,需要使用MSSP(移动签名服务提供商)将签名附加到签名面板。我研究了一些stackoverflow问题,做了如下工作。 首先,我创建pdf的校验和。在生成校验和之前,将空签名添加到pdf。生成校验和后,我将其作为数据发送到服务器,以便对文档进行签名。服务器给了我base64签名,我从base64签名中找到了证书链。现在我需要将签名附加到pdf,显示在Adobe rea

  • 我是新来的iText 7,我已经尝试添加ltv信息到现有的签名通过使用addolv()方法(下面提供的代码)...如果我理解正确的话,这个方法将crl或ocsp参数添加到现有的签名或时间戳中,然后对文档进行时间戳,但是生成的pdf文档没有启用ltv。然而,如果我首先用ocsp或crl列表签署文档,我就能够生成支持LTV的签名,这让我相信这个问题与某些证书丢失或未正确添加无关。因此,由于某种原因,a

  • 我有一个密钥库文件,其中有两个密钥:一个用于调试构建,另一个用于发布构建类型。因此,我的gradle构建脚本根据需要生成两个APK。现在,要部署调试构建apk,android gradle插件中有installDebug任务,但是部署发布构建apk怎么样?Andorid gradle插件没有像installRelease这样的任务。如何使用gradle将版本构建apk直接部署到连接的设备?

  • 问题内容: 我想建立一个不牺牲SEO的ajax网站。我的问题是:如果我的页面上有这样的链接: …当单击每个链接时,我想用相应的标签更新地址栏。因此,如果单击“猫”链接,则当前位置为http://example.com/#cats,我可以用它来显示我的Ajax内容。如果javascript关闭或用户是搜索引擎,他们将直接转到/ cats 问题答案: 您可以更改属性,它会更改当前的锚标识符,而无需导航

  • 在浏览了几天的网页和帖子之后,我仍然对如何将“csv”文件附件添加到使用Java“iText 5.3.1”创建的PDF文件中感到困惑。 在我继承的Java可执行文件中,创建了多个PDF文件,然后将它们连接到一个PDF文件中。现在,需要将一个“csv”文件附加到这个PDF文档中。在《iText in Action》(清单16.6)一书的第16章中,有一个例子使用PdfileSpecification

  • 问题内容: 如何使用iText签名pdf?我正在通过此LINK进行操作, 但不了解my_private_key.pfx。我真的需要数字签名证书吗?请澄清一下。提前致谢。 问题答案: 您在问题中提到的文档很好。您必须创建数字签名文件。 该链接具有使用PKCS文件和签署PDF文档的工具。它声称使用iText,因此您应该能够理解这些步骤。源代码在这里