我正在尝试使用视觉签名和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,c);
}
is.close();
}
除了文件疯狂,我没有在签名上看到任何文字.结果如下:
当我用itext库做类似的事情时,这就是它的外观
为什么视觉签名表示中缺少名称,位置和原因?我该如何解决这个问题?
解决方法
为什么视觉签名表示中缺少名称,位置和原因?
他们不在那里,因为他们没有画画.
iText表示可视化签名的默认方式是将这些信息添加到可视化中.
PDFBox’PDVisibleSigBuilder表示可视化签名的默认方式是没有这些信息.
既不是错误的也不是正确的,两者都只是默认值.
人们应该寻找这些信息的规范场所毕竟是签名小组.
我该如何解决这个问题?
签名可视化的实际内容由signatureProperties.buildSignature()期间的PDVisibleSigBuilder实例创建:
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,String imageObjectName,String imageName,String innerFormName,PDVisibleSignDesigner properties)
throws IOException
{
super.injectAppearanceStreams(holderFormStream,innterFormStream,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);
}
}
在Helvetica中写入“Hello”,大小为10,位于图像形式的左下方(实际显示的形式).
PS:在我看来,这背后的面向对象结构应该彻底改革.