pdfbox - 签名横向文件错误

pdfbox - sign landscape file error

我正在使用 pdfbox-1.8.8 对 PDF 文件执行签名功能。

在纵向模式下处理 PDF 文件效果很好。但是对于横向文件,我有一个问题

看来风景文件的坐标有误。

有人知道文件有什么问题吗?

这里是pdf file

的link

这是我用来签名的代码

public void signDetached(String inputFilePath, String outputFilePath, String signatureImagePath, Sign signProperties) {
    OutputStream outputStream = null;
    InputStream inputStream = null;
    PDDocument document = null;
    InputStream signImageStream = null;

    try {
        setTsaClient(null);
        document = PDDocument.load(inputFilePath);
        // create signature dictionary
        PDSignature signature = new PDSignature();
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
        signature.setName("VANDUC1102");
        signature.setLocation(null);
        String displayName = "Hello World, Document signed by VANDUC1102";
        String reason = reasonText+ " " + displayName;
        signature.setReason(reason);

        // the signing date, needed for valid signature
        signature.setSignDate(Calendar.getInstance());            
        int signatureInPage = signProperties.getPageNumber() + 1;
        signImageStream = new FileInputStream(new File(signatureImagePath));
        PDVisibleSignDesigner visibleSig = new PDVisibleSignDesigner(inputFilePath, signImageStream, signatureInPage);

        float xAxis = convertPixel2Point(signProperties.getX()) ;
        float yAxis = convertPixel2Point(signProperties.getY());               
        float signImageHeight = convertPixel2Point(signImageHeight);    
        float signImageWidth = convertPixel2Point(signImageWidth);

        visibleSig.xAxis(xAxis)
                .yAxis(yAxis)
                .zoom(0)
                .signatureFieldName("Signature")
                .height(signImageHeight)
                .width(signImageWidth);
        PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();

        signatureProperties.signerName(eiUser.getName())
                 .signerLocation(null)
                 .signatureReason(reason)
                 .preferredSize(0)
                 .page(signProperties.getPageNumber())
                 .visualSignEnabled(true)
                 .setPdVisibleSignature(visibleSig)
                 .buildSignature();
         // register signature dictionary and sign interface
        SignatureOptions signatureOptions = new SignatureOptions();
        signatureOptions.setVisualSignature(signatureProperties);
        signatureOptions.setPage(signatureInPage);
        document.addSignature(signature, this, signatureOptions);

        File outputFile = new File(outputFilePath);
        outputStream = new FileOutputStream(outputFile);
        inputStream = new FileInputStream(inputFilePath);
        IOUtils.copyStream(inputStream, outputStream);
        document.saveIncremental(inputStream, outputStream);
        outputStream.flush();
    } catch (COSVisitorException | SignatureException | IOException ex) {
        log.error("signDetached ", ex);
    } finally {
        IOUtils.closeStream(outputStream);
        IOUtils.closeStream(inputStream);
        IOUtils.closeStream(signImageStream);
        IOUtils.closeStream(document);
    }
}
private float convertPixel2Point(float pixel){
    return pixel * (float) 72/96;
}

正如我所说,此代码适用于纵向 PDF

谢谢。

相关页面的 Rotate 值非零。 PDFBox 视觉签名 类 完全忽略了这个值,所以必须给它坐标和尺寸,就好像页面没有旋转一样。

这可以通过添加以下 switch 语句来完成:

float xAxis = convertPixel2Point(/*signProperties.getX()*/x) ;
float yAxis = convertPixel2Point(/*signProperties.getY()*/y);               
float signImageHeight = convertPixel2Point(/*signImageHeight*/324);    
float signImageWidth = convertPixel2Point(/*signImageWidth*/309);

int rotation = getPageRotation(inputFilePath, page) % 360;
switch (rotation)
{
case 0:
    // all ok;
    break;
case 90:
    visibleSig.affineTransformParams(new byte[] {0, 1, -2, 0, 100, 0})
              .formaterRectangleParams(new byte[]{0, 0, 100, 100});

    float temp = yAxis;
    yAxis = visibleSig.getPageHeight() - xAxis - signImageWidth;
    xAxis = temp;

    temp = signImageHeight;
    signImageHeight = signImageWidth;
    signImageWidth = temp;

    break;
case 180:
    // Implement in a similar fashion
case 270:
    // Implement in a similar fashion
}

visibleSig.xAxis(xAxis)
          .yAxis(yAxis)
          .zoom(0)
          .signatureFieldName("Signature")
          .height(signImageHeight)
          .width(signImageWidth);

和以下方法:

private int getPageRotation(String documentPath, int page) throws IOException
{
    try (PDDocument document = PDDocument.load(documentPath))
    {
        List<?> pages = document.getDocumentCatalog().getAllPages();
        PDPage pageObject =(PDPage) pages.get(page);
        return pageObject.getRotation();
    }
}

对于 旋转 值 180 和 270,必须进行类似的修正。

SignLikeVanduc1102中的测试方法testLandscapeOriginaltestLandscapeFixed

从版本 2.0.5 开始,可以通过 adjustForRotation() 调用调整旋转页面的签名字段。在 CreateVisibleSignature.java example 中,这一行

visibleSignDesigner.xAxis(x).yAxis(y).zoom(zoomPercent);

必须改为:

visibleSignDesigner.xAxis(x).yAxis(y).zoom(zoomPercent).adjustForRotation();

更改(issue PDFBOX-3671)部分基于@mkl 的回答。它将不适用于 1.8.*.

2018 年 10 月 24 日更新:

2.0.12 之前的所有 2.0.* 版本都存在 adjustForRotation() 对于 200 x 100 图像尺寸 hard-coded 的问题。这已在 2.0.13 中修复。或者派生您自己的 PDVisibleSignDesigner 并使用正确的实现扩展 adjustForRotation()

public PDVisibleSignDesigner adjustForRotation()
{
    switch (rotation)
    {
        case 90:
            float temp = yAxis;
            yAxis = pageHeight - xAxis - imageWidth;
            xAxis = temp;

            affineTransform = new AffineTransform(
                    0, imageHeight / imageWidth, -imageWidth / imageHeight, 0, imageWidth, 0);

            temp = imageHeight;
            imageHeight = imageWidth;
            imageWidth = temp;
            break;

        case 180:
            float newX = pageWidth - xAxis - imageWidth;
            float newY = pageHeight - yAxis - imageHeight;
            xAxis = newX;
            yAxis = newY;

            affineTransform = new AffineTransform(-1, 0, 0, -1, imageWidth, imageHeight);
            break;

        case 270:
            temp = xAxis;
            xAxis = pageWidth - yAxis - imageHeight;
            yAxis = temp;

            affineTransform = new AffineTransform(
                    0, -imageHeight / imageWidth, imageWidth / imageHeight, 0, 0, imageHeight);

            temp = imageHeight;
            imageHeight = imageWidth;
            imageWidth = temp;
            break;

        case 0:
        default:
            break;
    }
    return this;
}