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中的测试方法testLandscapeOriginal
和testLandscapeFixed
)
从版本 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;
}
我正在使用 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中的测试方法testLandscapeOriginal
和testLandscapeFixed
)
从版本 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;
}