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

PDFBox克隆文档时字体丢失导致显示异常的技术求助

解决PDF克隆后字体缺失及显示异常问题

我来帮你搞定这个字体丢失的问题!你现在的克隆代码只处理了页面的基础属性和资源的表层克隆,但PDF的字体资源是嵌套在页面资源里的复杂对象,必须确保它们被完整克隆并关联到新文档,否则就会出现字体显示异常、字符缺失的情况。

问题根源

你原来的代码中,只是简单克隆了PDResources的字典对象,但没有递归处理其中的字体资源——这些字体对象并没有被真正添加到新文档的COS结构中,导致渲染时找不到对应的字体文件,自然就会出问题。而且原文档getFontsToSubset()里的字体子集信息,也没有被正确迁移到新文档。

修正方案:手动处理字体克隆

修改你设置页面资源的逻辑,遍历原页面资源中的所有字体,逐个克隆并关联到新文档的资源中:

cloneDoc = new PDDocument();
PDFCloneUtility cloner = new PDFCloneUtility(cloneDoc);

for(int pageIndex = 0; pageIndex < mainDoc.getNumberOfPages(); ++pageIndex) {
    PDPage page = mainDoc.getPage(pageIndex);
    PDPage newPage = new PDPage((COSDictionary) cloner.cloneForNewDocument(page.getCOSObject()));
    
    // 复制页面基础属性
    newPage.setCropBox(page.getCropBox());
    newPage.setMediaBox(page.getMediaBox());
    newPage.setRotation(page.getRotation());
    
    // 处理页面资源及字体
    if (page.getResources() != null) {
        // 克隆资源字典
        COSDictionary clonedResourcesDict = (COSDictionary) cloner.cloneForNewDocument(page.getResources().getCOSObject());
        PDResources newResources = new PDResources(clonedResourcesDict);
        
        // 遍历并克隆所有字体资源
        Map<String, PDFont> originalFonts = page.getResources().getFonts();
        for (Map.Entry<String, PDFont> fontEntry : originalFonts.entrySet()) {
            PDFont originalFont = fontEntry.getValue();
            // 克隆字体对象到新文档
            COSBase clonedFontBase = cloner.cloneForNewDocument(originalFont.getCOSObject());
            if (clonedFontBase instanceof COSDictionary) {
                // 根据克隆后的字体字典加载字体
                PDFont clonedFont = PDType0Font.load(cloneDoc, (COSDictionary) clonedFontBase);
                // 将克隆后的字体替换到新资源中
                newResources.put(fontEntry.getKey(), clonedFont);
            }
        }
        
        newPage.setResources(newResources);
    } else {
        newPage.setResources(new PDResources());
    }
    
    cloneDoc.addPage(newPage);
}

更简洁的替代方案:使用PDPage.copy方法

如果你使用的是较新版本的PDFBox,可以直接用PDPage#copyTo方法,它会自动处理所有资源(包括字体)的完整克隆,代码更简洁:

cloneDoc = new PDDocument();

for(int pageIndex = 0; pageIndex < mainDoc.getNumberOfPages(); ++pageIndex) {
    PDPage page = mainDoc.getPage(pageIndex);
    // 创建新页面并直接复制原页面的所有内容和资源
    PDPage newPage = new PDPage(page.getCOSObject());
    newPage.copyTo(cloneDoc);
    cloneDoc.addPage(newPage);
}

验证效果

修改完成后,你可以通过以下方式确认字体是否被正确克隆:

  • 遍历克隆文档的页面资源,检查getFonts()是否包含原文档getFontsToSubset()中的字体
  • 打开克隆后的PDF,查看文本的字体、字号是否正常,字符是否完整

内容的提问来源于stack exchange,提问作者V JDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:05:11