在日常工作中,我们经常遇到需要拆分大型PDF文件的场景:
比如将一份几百页的报告按章节拆分,或者把一个超大PDF 分割成多个便于传输的小文件,然后调用类似 MinerU 等智能文档识别工具去进一步处理。

然而,很多人踩过这个坑:拆分后的多个PDF文件加起来,竟然比原始文件大很多!有的甚至膨胀 2-3 倍。
今天我们就来介绍 PDFBox 中的三种拆分方案,看看哪一种能真正做到“体积几乎不膨胀”。
▌方案一:importPage 方式
PDDocument newDoc = new PDDocument();for (int i = start; i < end; i++) {PDPage page = sourceDoc.getPage(i);newDoc.importPage(page);}newDoc.save("part_" + index + ".pdf");
▌原理:直接导入页面引用,看似高效。
实测结果:❌ 总体积膨胀约2-3倍。因为每个新PDF都会复制原始文件的字体、图片等资源。
▌方案二:addPage + 压缩参数
for(int s=0; s<total; s+=PER){int e = Math.min(s+PER, total);try(PDDocument sub = new PDDocument()){for(int p=s; p<e; p++){PDPage pg = source.getPage(p);sub.addPage(pg);}// 关键:保存传入压缩参数,大幅瘦身sub.save(new File("part"+idx+".pdf"), compressCfg);idx++;}}
▌原理:复制页面并显式传入压缩配置。
实测结果:⚠️ 比方案一略好,但总体积仍膨胀2倍左右。压缩参数只能缓解,无法根治。
▌方案三:Splitter 方案(最佳推荐)
import org.apache.pdfbox.multipdf.Splitter;Splitter splitter = new Splitter();splitter.setSplitAtPage(50); // 每50页一个文件List<PDDocument> splitDocuments = splitter.split(sourceDoc);int idx = 1;for (PDDocument doc : splitDocuments) {doc.save("part_" + idx + ".pdf");doc.close();idx++;}
▌原理:Splitter是PDFBox专门为拆分场景设计的工具,它会智能复用原始PDF中的共享资源,而不是每个文件都复制一份。
实测结果:✅ 总体积几乎只 增加1% 左右!
▌对比总结:
方案 体积膨胀 速度 推荐度
importPage 2-3倍 快 ⭐
copy + 压缩 约2倍 中等 ⭐⭐
Splitter 约1% 快 ⭐⭐⭐⭐⭐
▌为什么 Splitter 能做到体积几乎不膨胀?
PDF文件内部有字体、图片、颜色空间等共享资源。方案一和方案二在拆分时,每个小PDF都会复制一份完整的资源副本,导致总体积膨胀。
而Splitter采用了智能资源复用机制:
多个拆分文件共享同一份资源定义,仅复制实际被页面引用的资源,保持原始压缩 方式不变。
▌注意事项
使用Splitter时,如果原始PDF包含破损的书签或链接,可能遇到空指针异常。解决方法很简单:拆分前清除书签即可。
// 1. 清除书签,避免拆分报错if (sourceDoc.getDocumentCatalog().getDocumentOutline() != null) {sourceDoc.getDocumentCatalog().setDocumentOutline(null);}// 2. 清除命名目标(Named Destinations)...// 3. 遍历所有页面,清除页面中的链接注解(这是关键!)...
课代表小结
如果你需要拆分大型PDF文件,并且希望拆分后的总体积几乎不膨胀,Splitter方案,是你的最佳选择。它不仅体积控制出色,代码也简洁优雅,性能表现优秀。
下次遇到PDF拆分需求,记得用对方法哦!
▌往期推荐:
深度解析|五大主流 Agent 记忆设计范式,从原理到落地全覆盖
好了,本期内容就是这么多,希望能够帮助到您,感谢您能读到最后,如果觉得内容不错,请您点赞转发给予鼓励。👇👇👇

夜雨聆风