gpt4 book ai didi

java - pdfbox 1.8.8 视觉签名

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:01:41 26 4
gpt4 key购买 nike

我正在尝试生成带有视觉签名和 pdfbox 的 PDF。我有两个流,pdfbox 似乎只能处理文件。如果没有三个临时文件,我无法让它工作。我可以从here看到该 API 已更改,但它仍然处理文件。

public void signPdf(InputStream originalPdf, OutputStream signedPdf,
InputStream image, float x, float y,
String name, String location, String reason) {

File temp = null;
File temp2 = null;
File scratchFile = null;
RandomAccessFile randomAccessFile = null;
OutputStream tempOut = null;
InputStream tempIn = null;
try {
/* Copy original to temporary file */
temp = File.createTempFile("signed1", ".tmp");
tempOut = new FileOutputStream(temp);
copyStream(originalPdf, tempOut);
tempOut.close();

/* Read temporary file to second temporary file and stream */
tempIn = new FileInputStream(temp);
temp2 = File.createTempFile("signed2", ".tmp");
tempOut = new FileOutputStream(temp2);
copyStream(tempIn, tempOut);
tempIn.close();
tempIn = new FileInputStream(temp2);

scratchFile = File.createTempFile("signed3", ".bin");
randomAccessFile = new RandomAccessFile(scratchFile, "rw");

/* Read temporary file */
PDDocument document = PDDocument.load(temp, randomAccessFile);
document.getCurrentAccessPermission().setCanModify(false);

PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName(name);
signature.setLocation(location);
signature.setReason(reason);
signature.setSignDate(Calendar.getInstance());

PDVisibleSignDesigner signatureDesigner = new PDVisibleSignDesigner(
document, image, document.getNumberOfPages());
signatureDesigner.xAxis(250).yAxis(60).zoom(-90).signatureFieldName("signature");

PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
signatureProperties.signerName(name).signerLocation(location)
.signatureReason(reason).preferredSize(0).page(1)
.visualSignEnabled(true).setPdVisibleSignature(signatureDesigner)
.buildSignature();

SignatureOptions options = new SignatureOptions();
options.setVisualSignature(signatureProperties);

document.addSignature(signature, dataSigner, options);

/* Sign */
document.saveIncremental(tempIn, tempOut);
document.close();
tempIn.close();

/* Copy temporary file to an output stream */
tempIn = new FileInputStream(temp2);
copyStream(tempIn, signedPdf);
} catch (IOException e) {
logger.error("PDF signing failure", e);
} catch (COSVisitorException e) {
logger.error("PDF creation failure", e);
} catch (SignatureException e) {
logger.error("PDF signing failure", e);
} finally {
closeStream(originalPdf);
closeStream(signedPdf);
closeStream(randomAccessFile);
closeStream(tempOut);
deleteTempFile(temp);
deleteTempFile(temp2);
deleteTempFile(scratchFile);
}
}

private void deleteTempFile(File tempFile) {
if (tempFile != null && tempFile.exists() && !tempFile.delete()) {
tempFile.deleteOnExit();
}
}

private void closeStream(Closeable is) {
if (is!= null) {
try {
is.close();
} catch (IOException e) {
logger.error("failure", e);
}
}
}

private void copyStream(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[1024];
int c;
while ((c = is.read(buffer)) != -1) {
os.write(buffer, 0, c);
}
is.close();
}

除了乱七八糟的文件外,我在签名上看不到任何文字。结果是这样的:

enter image description here

这就是我用 itext 库做类似事情时的样子

enter image description here

为什么视觉签名表示中缺少名称、位置和原因?我该如何解决?

最佳答案

为什么视觉签名表示中缺少姓名、位置和原因?

它们不存在是因为它们没有被绘制。

iText 表示可视化签名的默认方式是将这些信息添加到可视化中。

PDFBox 的 PDVisibleSigBuilder 表示可视化签名的默认方式没有此类信息。

既不对也不对,都只是默认。

毕竟,人们寻找此类信息的规范位置是签名面板。

我该如何解决?

签名可视化的实际内容由 PDVisibleSigBuilder 实例在 signatureProperties.buildSignature() 期间创建:

public void buildSignature() throws IOException
{
PDFTemplateBuilder builder = new PDVisibleSigBuilder();
PDFTemplateCreator creator = new PDFTemplateCreator(builder);
setVisibleSignature(creator.buildPDF(getPdVisibleSignature()));
}

因此,通过替换

    signatureProperties.signerName(name).signerLocation(location)
.signatureReason(reason).preferredSize(0).page(1)
.visualSignEnabled(true).setPdVisibleSignature(signatureDesigner)
.buildSignature();

在你的代码中

    signatureProperties.signerName(name).signerLocation(location)
.signatureReason(reason).preferredSize(0).page(1)
.visualSignEnabled(true).setPdVisibleSignature(signatureDesigner);

PDFTemplateBuilder builder = new ExtSigBuilder();
PDFTemplateCreator creator = new PDFTemplateCreator(builder);
signatureProperties.setVisibleSignature(creator.buildPDF(signatureProperties.getPdVisibleSignature()));

对于此 PDVisibleSigBuilder 类的自定义版本 ExtSigBuilder,您可以在那里绘制任何您想要的内容,例如:

class ExtSigBuilder extends PDVisibleSigBuilder
{
String fontName;

public void createImageForm(PDResources imageFormResources, PDResources innerFormResource,
PDStream imageFormStream, PDRectangle formrect, AffineTransform affineTransform, PDJpeg img)
throws IOException
{
super.createImageForm(imageFormResources, innerFormResource, imageFormStream, formrect, affineTransform, img);

PDFont font = PDType1Font.HELVETICA;
fontName = getStructure().getImageForm().getResources().addFont(font);

logger.info("Added font to image form: " + fontName);
}

public void injectAppearanceStreams(PDStream holderFormStream, PDStream innterFormStream, PDStream imageFormStream,
String imageObjectName, String imageName, String innerFormName, PDVisibleSignDesigner properties)
throws IOException
{
super.injectAppearanceStreams(holderFormStream, innterFormStream, imageFormStream, imageObjectName, imageName, innerFormName, properties);

String imgFormComment = "q " + 100 + " 0 0 50 0 0 cm /" + imageName + " Do Q\n";
String text = "BT /" + fontName + " 10 Tf (Hello) Tj ET\n";
appendRawCommands(getStructure().getImageFormStream().createOutputStream(), imgFormComment + text);

logger.info("Added text commands to image form: " + text);
}
}

在图像窗体的左下方(该窗体实际上显示了一些东西)以 10 号字体用 Helvetica 书写“Hello”。

PS:在我看来,这背后的面向对象结构应该彻底改革。

关于java - pdfbox 1.8.8 视觉签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27926407/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com