使用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:
- 将字体文件(如
simsun.ttc)放入项目资源目录 - 修改代码添加字体加载与替换逻辑:
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
相关产品推荐
相关产品推荐

