You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PDFBox 2.0.24合并PDF时,如何移除重复嵌入的字体子集?

解决PDFBox合并PDF时重复嵌入字体子集的问题

一、手动控制PDFBox的字体资源复用

PDFBox默认合并逻辑不会严格复用相同字体子集,你可以自己写逻辑来复用:

  • 遍历所有待合并PDF的页面,提取每个页面的字体,用字体名+字符集哈希作为唯一标识,把相同的字体实例存起来,后续页面遇到重复字体时直接复用,不再重复嵌入。
  • 参考代码片段:
    PDDocument targetDoc = new PDDocument();
    Map<String, PDFont> reusedFontMap = new HashMap<>();
    
    for (String pdfPath : 你的PDF路径列表) {
        try (PDDocument sourceDoc = PDDocument.load(new File(pdfPath))) {
            for (PDPage page : sourceDoc.getPages()) {
                PDPage importedPage = targetDoc.importPage(page);
                PDResources pageResources = importedPage.getResources();
                
                // 遍历页面字体资源
                for (COSName fontName : pageResources.getFontNames()) {
                    PDFont currentFont = pageResources.getFont(fontName);
                    // 生成字体唯一标识,确保相同子集的字体能匹配
                    String fontKey = currentFont.getName() + "_" + currentFont.getFontDescriptor().getFontFile2().getCOSObject().getKey();
                    
                    if (reusedFontMap.containsKey(fontKey)) {
                        // 替换成已复用的字体
                        pageResources.put(fontName, reusedFontMap.get(fontKey));
                    } else {
                        reusedFontMap.put(fontKey, currentFont);
                    }
                }
            }
        }
    }
    targetDoc.save("合并后优化版.pdf");
    targetDoc.close();
    
    注意:要确保复用的字体包含所有需要的字符,不然可能出现乱码,测试时要重点检查特殊字符。

二、用PDFBox自带的优化器后处理

PDFBox有个PDFOptimizer工具,专门用来优化PDF体积,开启字体优化选项试试:

PDDocument mergedDoc = PDDocument.load(new File("合并后的大文件.pdf"));
PDFOptimizer optimizer = new PDFOptimizer();
optimizer.setOptimizeFonts(true); // 打开字体优化开关
optimizer.optimize(mergedDoc);
mergedDoc.save("优化后的文件.pdf");
mergedDoc.close();

这个工具会自动检测重复字体并合并,但如果你的文件是PDF/A格式,可能需要额外调整参数保证兼容性。

三、先预处理单个PDF

如果待合并的单个PDF本身就有冗余字体子集,可以先单独优化每个文件:

  • 用PDFBox移除每个PDF里未被使用的字体子集,减少源文件的字体冗余:
    try (PDDocument singleDoc = PDDocument.load(new File("单个PDF文件.pdf"))) {
        PDResources resources = singleDoc.getDocumentCatalog().getPages().get(0).getResources();
        // 遍历字体,移除未被使用的
        for (COSName fontName : new HashSet<>(resources.getFontNames())) {
            PDFont font = resources.getFont(fontName);
            if (!checkFontIsUsed(singleDoc, font)) { // 自己写方法判断字体是否被页面使用
                resources.remove(fontName);
            }
        }
        singleDoc.save("预处理后的单个文件.pdf");
    }
    
    其中checkFontIsUsed需要解析页面内容流,判断字体名称是否被引用,避免误删必要字体。

四、换用iText合并试试

如果PDFBox的方案都不管用,可以换iText 7.x版本来合并,它默认会自动复用相同字体子集,对重复字体的处理更成熟:

PdfWriter writer = new PdfWriter("合并后优化版.pdf");
PdfDocument mergedDoc = new PdfDocument(writer);
PdfMerger merger = new PdfMerger(mergedDoc);

for (String pdfPath : 你的PDF路径列表) {
    PdfDocument sourceDoc = new PdfDocument(new PdfReader(pdfPath));
    merger.merge(sourceDoc, 1, sourceDoc.getNumberOfPages());
    sourceDoc.close();
}
mergedDoc.close();

内容的提问来源于stack exchange,提问作者ma hei pang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:26:32