Java Apache PdfBox嵌入外部字体至PDF页面的实现方法咨询
在Apache PdfBox中嵌入并使用外部字体的完整方案
我经常帮人解决PdfBox相关的问题,嵌入外部字体这块其实流程很清晰,咱们一步步来:
1. 先搞定依赖和字体文件
首先确保你的项目里已经引入了PdfBox的依赖,如果你用Maven的话,在pom.xml里加这段:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.32</version> <!-- 建议用最新稳定版 --> </dependency>
然后把你要用到的外部字体文件(比如custom-font.ttf或者my-font.otf)放在项目的src/main/resources目录下,或者记好它的本地绝对路径。
2. 加载外部字体(核心步骤)
PdfBox推荐用PDType0Font来加载外部字体,它会自动处理字体嵌入,还支持子集嵌入(只嵌入用到的字符,减小PDF体积)。这里有两种加载方式:
从资源目录加载
如果字体在资源文件夹里,用输入流加载:
try (InputStream fontStream = YourClassName.class.getResourceAsStream("/custom-font.ttf")) { // 第二个参数设为true表示嵌入字体 PDType0Font customFont = PDType0Font.load(document, fontStream, true); } catch (IOException e) { e.printStackTrace(); }
从本地文件路径加载
如果字体在本地某个路径下:
File fontFile = new File("C:/fonts/custom-font.ttf"); try { PDType0Font customFont = PDType0Font.load(document, fontFile, true); } catch (IOException e) { e.printStackTrace(); }
注意:别用
PDTrueTypeFont了,它是旧的API,而且不支持子集嵌入,生成的PDF会更大。
3. 在PDF页面中使用嵌入的字体
分两种场景给你示例:
场景1:创建全新的PDF并使用外部字体
完整的代码示例,用try-with-resources自动关闭资源,避免内存泄漏:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType0Font; import java.io.File; import java.io.IOException; import java.io.InputStream; public class EmbedFontExample { public static void main(String[] args) { // 创建新PDF文档 try (PDDocument document = new PDDocument()) { PDPage page = new PDPage(); document.addPage(page); // 加载外部字体 try (InputStream fontStream = EmbedFontExample.class.getResourceAsStream("/custom-font.ttf")) { PDType0Font customFont = PDType0Font.load(document, fontStream, true); // 创建内容流,开始写内容 try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { // 设置字体和字号 contentStream.setFont(customFont, 12); // 绘制文本,坐标(x=100, y=700),PDF的坐标原点在左下角 contentStream.beginText(); contentStream.newLineAtOffset(100, 700); contentStream.showText("这是用外部嵌入字体写的文本!"); contentStream.endText(); } } // 保存PDF document.save(new File("output-with-custom-font.pdf")); System.out.println("PDF生成成功,字体已嵌入!"); } catch (IOException e) { e.printStackTrace(); } } }
场景2:修改现有PDF,在页面中添加带外部字体的文本
如果你要给已有的PDF加内容,代码大概是这样:
try (PDDocument document = PDDocument.load(new File("existing-document.pdf"))) { PDPage page = document.getPage(0); // 获取第一页(索引从0开始) try (InputStream fontStream = YourClassName.class.getResourceAsStream("/custom-font.ttf")) { PDType0Font customFont = PDType0Font.load(document, fontStream, true); try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) { contentStream.setFont(customFont, 14); contentStream.beginText(); contentStream.newLineAtOffset(150, 600); contentStream.showText("给现有PDF添加的外部字体文本"); contentStream.endText(); } } document.save(new File("modified-document.pdf")); } catch (IOException e) { e.printStackTrace(); }
4. 一定要注意的几个点
- 字体版权:不是所有字体都允许嵌入,有些商业字体有版权限制,使用前要确认授权!
- 子集嵌入:加载字体时第三个参数设为
true就会自动启用子集嵌入,只嵌入你用到的字符,能大幅减小PDF体积。如果设为false会嵌入整个字体文件,PDF会很大。 - 资源关闭:所有的流(字体流、内容流、文档)都要记得关闭,用try-with-resources是最稳妥的方式,不用手动写close()。
- 字符支持:如果你的字体不支持中文或者其他特殊字符,那显示会有问题,要选对应字符集的字体。
内容的提问来源于stack exchange,提问作者user9369410
相关产品推荐
相关产品推荐

