如何使用PDFBOX回退PDF的最后一次增量更新(签名场景)
如何用Apache PDFBox回退PDF的最后一次增量更新
我之前刚好解决过类似的需求,用Apache PDFBox回退PDF的最后一次增量更新其实核心就是定位到倒数第二个%%EOF标记,然后截断文件到这个位置就行——毕竟PDF的增量更新就是在原文档末尾追加新内容,每段增量末尾都会带%%EOF。下面是具体的实现思路和代码:
核心原理
PDF的增量更新(比如数字签名后的追加内容)是直接在原始文档字节流的末尾添加新的修订数据,每个完整的修订段末尾都会以%%EOF标记结束。所以要回退最后一次增量,只需要找到文件中倒数第二个%%EOF的位置,然后将文件截断到该位置即可,这样就会丢弃最后一次追加的所有内容,回到上一次修订的状态。
代码实现
这里我们直接操作PDF的原始字节流(避免PDFBox解析重写文档导致的格式变化),结合简单的字符串查找来定位%%EOF标记:
import org.apache.commons.io.IOUtils; import java.io.*; import java.util.ArrayList; import java.util.List; public class PdfRollbackLastIncrement { public static void rollbackLastIncrement(File inputPdf, File outputPdf) throws IOException { // 读取原始PDF的全部字节内容 byte[] pdfBytes = IOUtils.toByteArray(new FileInputStream(inputPdf)); String pdfString = new String(pdfBytes); // 找到所有%%EOF标记的结束位置 List<Integer> eofEndPositions = new ArrayList<>(); final String EOF_MARKER = "%%EOF"; int currentIndex = pdfString.indexOf(EOF_MARKER); while (currentIndex != -1) { // 记录标记的结束索引(标记长度+起始索引) eofEndPositions.add(currentIndex + EOF_MARKER.length()); // 继续查找下一个标记 currentIndex = pdfString.indexOf(EOF_MARKER, currentIndex + 1); } // 检查是否存在至少两次修订(至少两个%%EOF) if (eofEndPositions.size() >= 2) { // 取倒数第二个%%EOF的结束位置作为截断点 int rollbackPoint = eofEndPositions.get(eofEndPositions.size() - 2); byte[] rolledBackBytes = new byte[rollbackPoint]; System.arraycopy(pdfBytes, 0, rolledBackBytes, 0, rollbackPoint); // 将截断后的字节写入新文件 try (FileOutputStream fos = new FileOutputStream(outputPdf)) { fos.write(rolledBackBytes); } System.out.println("成功回退最后一次增量更新,输出文件:" + outputPdf.getAbsolutePath()); } else { throw new IllegalArgumentException("该PDF没有足够的增量修订,无法执行回退操作"); } } // 测试示例 public static void main(String[] args) { try { rollbackLastIncrement( new File("signed_document.pdf"), new File("restored_original.pdf") ); } catch (IOException e) { e.printStackTrace(); } } }
注意事项
- 依赖说明:代码中用到了
org.apache.commons.io.IOUtils来简化文件读取,你需要确保项目中引入了Apache Commons IO依赖,或者替换为原生Java IO的读取方式(比如用FileInputStream逐字节读取)。 - 特殊情况处理:少数PDF的
%%EOF标记可能后面跟着空白字符或注释行,这种情况下可以调整查找逻辑,比如查找%%EOF后面的换行符,确保定位到的是完整的修订结束点。 - 准确性:这种直接操作字节流的方式不会解析PDF内容,所以能100%保留原始文档的格式和内容,比通过PDFBox加载后再保存的方式更准确(后者会重写整个文档结构)。
内容的提问来源于stack exchange,提问作者Abhishek Dadhich
相关产品推荐
相关产品推荐

