我们如何使用pdfbox恢复pdf中的最后一次增量更新?
例如 Original document Signed document
当我使用增量保存对原始文档进行数字签名(证书签名)时,我会收到签名文档。在检查签名文件的来源后,我可以看到" %% EOF"正在呈现2次。如果我手动删除最后一个" %% EOF"连同其内容,我可以看到PDF返回其初始状态,这与原始文档非常相似。
我该如何务实地做到这一点?
我正在使用PDFBOX v2.0.8
最诚挚的问候, 阿布舍克巴克
答案 0 :(得分:2)
有更先进的方法,而且还有不太先进的方法。
这是最简单的一个:它会搜索%%EOF
标记,然后立即切断。这可能与原始的先前版本不同,因为该标记后面可能是可选的行尾标记。但是,除非先前的修订版已签名或线性化,否则带有行尾标记的变体和不具有行标记的变体等同于PDF文件。
为了搜索%%EOF
标记,我们使用来自twitter / elephant-bird项目的StreamSearcher
类,参见this earlier stack overflow answer:
public List<Long> simpleApproach(InputStream pdf) throws IOException {
StreamSearcher streamSearcher = new StreamSearcher("%%EOF".getBytes());
List<Long> results = new ArrayList<>();
long revisionSize = 0;
long diff;
while ((diff = streamSearcher.search(pdf)) > -1) {
revisionSize += diff;
results.add(revisionSize);
}
return results;
}
为了只复制所需的字节数,我们使用Guava ByteStreams
类。 (有许多替代方案,例如Apache Commons IO,但是Guava恰好已经存在于我的测试项目依赖项中。)
List<Long> simpleSizes = null;
try ( InputStream resource = GET_DOCUMENT_INPUTSTREAM) {
simpleSizes = simpleApproach(resource);
}
if (1 < simpleSizes.size()) {
try ( InputStream resource = GET_DOCUMENT_INPUTSTREAM;
OutputStream file = new FileOutputStream("previousRevision.pdf")) {
InputStream revision = ByteStreams.limit(resource, simpleSizes.get(simpleSizes.size() - 2));
ByteStreams.copy(revision, file);
}
}
GET_DOCUMENT_INPUTSTREAM
可能是new FileInputStream(PDF_PATH)
或new ByteArrayInputStream(PDF_BYTES)
或您必须为PDF重复检索InputStream
的任何方法。如果是这些示例(FileInputStream
,ByteArrayInputStream
),您甚至可以使用reset()
重复使用相同的流。