使用PDFBox合并PDF时出现Expected string, found COSDictionary错误如何解决
错误原因
该报错是由于待合并的PDF存在不符合PDF规范的结构:PDF名称树(NameTree)中ID节点的K属性预期为字符串类型,但出错的PDF文件中该属性存储的是字典(COSDictionary),触发PDFBox的类型校验失败。
解决方案
方案1:逐页复制合并(兼容性最高,无需修改源文件)
该方法跳过全局名称树、ID树的合并逻辑,仅复制页面内容,适配绝大多数非规范PDF的合并需求,代码示例如下:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class PdfMergeTest { public static void main(String[] args) throws IOException { try (PDDocument targetDoc = new PDDocument()) { // 加载所有待合并的PDF File[] sourceFiles = new File[]{new File("D://1.pdf"), new File("D://2.pdf")}; for (File file : sourceFiles) { try (PDDocument sourceDoc = PDDocument.load(file)) { // 逐页添加到目标文档 for (PDPage page : sourceDoc.getPages()) { targetDoc.addPage(page); } } } // 保存合并结果 Path mergedTempFile = Files.createTempFile("merge_", ".pdf"); targetDoc.save(mergedTempFile.toFile()); } } }
方案2:自定义合并工具跳过ID树合并
如果需要保留PDFMergerUtility的表单、书签合并等能力,可以继承PDFMergerUtility重写mergeIDTree方法,跳过ID树合并的校验逻辑:
import org.apache.pdfbox.multipdf.PDFMergerUtility; import org.apache.pdfbox.pdmodel.PDDocument; import java.io.IOException; // 自定义合并工具类 class CustomPDFMerger extends PDFMergerUtility { @Override protected void mergeIDTree(PDDocument destination, PDDocument source) throws IOException { // 空实现,跳过ID树合并步骤 } } // 调用示例 public class MergeTest { public static void main(String[] args) throws IOException { CustomPDFMerger merger = new CustomPDFMerger(); Path mergedTempFile = Files.createTempFile("merge_", ".pdf"); merger.setDestinationFileName(mergedTempFile.toString()); merger.addSource(new File("D://1.pdf")); merger.addSource(new File("D://2.pdf")); merger.mergeDocuments(null); } }
方案3:预处理修复源PDF结构
如果必须保留ID树信息,可以先加载PDF清理异常的ID树节点后再合并:
import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import java.io.File; import java.io.IOException; private PDDocument preprocessPdf(File file) throws IOException { PDDocument doc = PDDocument.load(file); PDDocumentCatalog catalog = doc.getDocumentCatalog(); if (catalog.getNames() != null) { // 移除异常的ID树节点 catalog.getNames().getCOSObject().removeItem(COSName.getPDFName("IDTree")); } return doc; }
内容的提问来源于stack exchange,提问作者Darshan
相关产品推荐
相关产品推荐

