Cyr*_*aud 5 java pdf signing inputstream pdfbox
我想在不使用临时文件的情况下从PDF文件中签署InputStream.
在这里我将InputStream转换为File,这工作正常:
InputStream inputStream = this.signatureObjPAdES.getSignatureDocument().getInputStream();
OutputStream outputStream = new FileOutputStream(new File("C:/temp.pdf"));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
PDDocument document = PDDocument.load(new File("C:/temp.pdf"));
...
document.addSignature(new PDSignature(this.dts.getDocumentTimeStamp()), this);
document.saveIncremental(new FileOutputStream("C:/result.pdf");
document.close();
Run Code Online (Sandbox Code Playgroud)
但我想直接这样做:
PDDocument document = PDDocument.load(inputStream);
Run Code Online (Sandbox Code Playgroud)
问题:跑步时
Exception in thread "main" java.lang.NullPointerException
at java.io.RandomAccessFile.<init>(Unknown Source)
at org.apache.pdfbox.io.RandomAccessBufferedFileInputStream.<init>(RandomAccessBufferedFileInputStream.java:77)
at org.apache.pdfbox.pdmodel.PDDocument.saveIncremental(PDDocument.java:961)
Run Code Online (Sandbox Code Playgroud)
欢迎所有想法.
谢谢.
编辑:它现在正在使用PDFBox 2.0.0的发布.
直接的障碍在于方法PDDocument.saveIncremental()本身:
Run Code Online (Sandbox Code Playgroud)public void saveIncremental(OutputStream output) throws IOException { InputStream input = new RandomAccessBufferedFileInputStream(incrementalFile); COSWriter writer = null; try { writer = new COSWriter(output, input); writer.write(this, signInterface); writer.close(); } finally { if (writer != null) { writer.close(); } } }
第一行中使用的成员仅在带有参数的incrementalFile过程中设置。PDDocument.loadFile
因此,不能使用该方法。
幸运的是,该方法PDDocument.saveIncremental()仅使用公开可用的方法和值signInterface,但您知道它的值,因为您在调用之前的代码行中设置了它saveIncremental:
document.addSignature(new PDSignature(this.dts.getDocumentTimeStamp()), this);
document.saveIncremental(new FileOutputStream("C:/result.pdf"));
Run Code Online (Sandbox Code Playgroud)
因此,PDDocument.saveIncremental()您可以在代码中执行等效操作,而不是调用。
为此,您还需要 的替换值InputStream input。它需要返回一个与inputStream您的内容相同的流
PDDocument document = PDDocument.load(inputStream);
Run Code Online (Sandbox Code Playgroud)
所以你需要使用该流两次。由于您没有说是否inputStream可以重置,我们将首先将其复制到byte[]我们转发到PDDocument.load和 的a 中new COSWriter。
因此,替换你的
PDDocument document = PDDocument.load(inputStream);
...
document.addSignature(new PDSignature(this.dts.getDocumentTimeStamp()), this);
document.saveIncremental(new FileOutputStream("C:/result.pdf"));
document.close();
Run Code Online (Sandbox Code Playgroud)
经过
byte[] inputBytes = IOUtils.toByteArray(inputStream);
PDDocument document = PDDocument.load(new ByteArrayInputStream(inputBytes));
...
document.addSignature(new PDSignature(this.dts.getDocumentTimeStamp()), this);
saveIncremental(new FileOutputStream("C:/result.pdf"),
new ByteArrayInputStream(inputBytes), document, this);
document.close();
Run Code Online (Sandbox Code Playgroud)
saveIncremental并在您的类中添加一个受原始方法启发的新方法PDDocument.saveIncremental():
void saveIncremental(OutputStream output, InputStream input, PDDocument document, SignatureInterface signatureInterface) throws IOException
{
COSWriter writer = null;
try
{
writer = new COSWriter(output, input);
writer.write(document, signatureInterface);
writer.close();
}
finally
{
if (writer != null)
{
writer.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我上面说了
由于您没有说是否
inputStream可以重置,我们将首先将其复制到byte[]我们转发到PDDocument.load和 的a 中new COSWriter。
实际上这样做还有另一个原因:COSWriter.doWriteSignature()像这样检索原始 PDF 的长度:
Run Code Online (Sandbox Code Playgroud)long inLength = incrementalInput.available();
不过,国家的文件InputStream.available():
请注意,虽然 的某些实现
InputStream将返回流中的字节总数,但许多实现不会返回。
因此,要重用而不是像上面inputStream那样使用 abyte[]和s,不仅需要支持,而且还需要成为将流中的总字节数返回为 的少数实现之一。ByteArrayInputStreaminputStreamreset()InputStreamavailable
FileInputStream并且ByteArrayInputStream两者都将流中的总字节数返回为available。
InputStream使用泛型而不是这两个时可能还会出现更多问题。
| 归档时间: |
|
| 查看次数: |
5173 次 |
| 最近记录: |