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

使用PDFBox 2.0.26转PDF为图片时STSong-Light字体缺失问题求解

问题描述

使用PDFBox 2.0.26进行PDF转图片操作,Maven依赖配置如下:

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>2.0.26</version>
</dependency>

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.26</version>
</dependency>

编写的转换代码:

FileInputStream fin = new FileInputStream("/path/to/sample.pdf");
try(final PDDocument doc = PDDocument.load(fin)){

    PDFRenderer pdfRenderer = new PDFRenderer((doc));

    BufferedImage bim = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
    File myObj = new File("/path/to/sample.png");
    FileOutputStream fos = new FileOutputStream(myObj);
    ImageIOUtil.writeImage(bim, "png", fos);
    fin.close();
    fos.close();

} catch (IOException e) {
    System.out.println("error");
}

程序在macOS上可正常运行(仅图片字体与原PDF不一致),但在Linux服务器上运行时中文字符丢失。源PDF使用的字体为STSong-Light,转换后Linux环境下的图片中中文字符无法显示。

解决方案

原因分析

Linux服务器默认缺少STSong-Light这类中文字体,PDFBox渲染PDF时找不到对应字体,若没有合适的 fallback 字体兜底,就会导致中文字符丢失。而macOS系统自带部分中文字体,因此能显示内容但字体与原PDF不一致。

方法一:在Linux服务器上安装对应字体

  • 下载STSong-Light字体文件(或兼容的宋体字体文件,如simsun.ttc)
  • 将字体文件复制到Linux系统字体目录,通常为/usr/share/fonts或~/.fonts
  • 执行命令更新字体缓存:
fc-cache -fv

重启应用后,PDFBox即可找到对应字体完成渲染。

方法二:在代码中配置字体替换

若无法在服务器上安装字体,可通过代码指定自定义字体作为 fallback:

  1. 将字体文件(如simsun.ttc)放入项目资源目录
  2. 修改代码添加字体加载与替换逻辑:
FileInputStream fin = new FileInputStream("/path/to/sample.pdf");
try(final PDDocument doc = PDDocument.load(fin)){
    // 加载自定义字体
    InputStream fontStream = YourClass.class.getResourceAsStream("/simsun.ttc");
    PDType0Font font = PDType0Font.load(doc, fontStream);
    
    // 设置字体替换映射
    FontMapper fontMapper = new DefaultFontMapper();
    fontMapper.put("STSong-Light", font);
    
    PDFRenderer pdfRenderer = new PDFRenderer(doc);
    // 给渲染器绑定自定义字体映射
    pdfRenderer.setFontMapper(fontMapper);

    BufferedImage bim = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
    File myObj = new File("/path/to/sample.png");
    try (FileOutputStream fos = new FileOutputStream(myObj)) {
        ImageIOUtil.writeImage(bim, "png", fos);
    }
    fin.close();

} catch (IOException e) {
    e.printStackTrace(); // 打印详细错误信息便于排查
}

注意:

  • 确保字体文件路径正确,且打包时包含该文件
  • 使用try-with-resources自动管理流资源,避免手动关闭时的异常

方法三:配置PDFBox字体搜索路径

创建pdfbox.fontpath配置文件,将自定义字体所在目录路径写入其中,放置在项目类路径下,PDFBox会自动扫描该路径下的字体文件。

额外优化建议
  • 替换原代码中的流处理为try-with-resources,避免资源泄漏:
try (FileInputStream fin = new FileInputStream("/path/to/sample.pdf");
     FileOutputStream fos = new FileOutputStream(myObj)) {
    // 核心转换逻辑
}
  • 捕获异常时打印完整堆栈信息,而非仅输出"error",便于定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:45:28