Java中如何将.ttf字体嵌入现有PDF(支持Pdfbox/OpenPDF)
Java中嵌入TTF字体到现有PDF的实现方案
一、使用Apache Pdfbox实现
核心操作逻辑
- 从输入流加载目标PDF,全程内存操作
- 加载TTF字体并标记为需嵌入
- 将字体注入PDF全局资源字典,确保出现在字体列表中
代码示例
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; public class PdfboxFontEmbedder { public byte[] embedFontToPdf(byte[] sourcePdfBytes, InputStream ttfFontStream) throws Exception { // 加载现有PDF到内存 try (PDDocument document = PDDocument.load(new ByteArrayInputStream(sourcePdfBytes))) { // 加载TTF字体并设置嵌入属性 PDTrueTypeFont embeddedFont = PDTrueTypeFont.load(document, ttfFontStream, true); embeddedFont.setEmbedded(true); embeddedFont.setSubset(false); // 嵌入完整字体,保证字体列表可见 // 将字体添加到PDF全局资源 PDResources resources = document.getDocumentCatalog().getResources(); if (resources == null) { resources = new PDResources(); document.getDocumentCatalog().setResources(resources); } // 自定义字体名称,避免和现有字体冲突 resources.put("CustomEmbeddedFont", embeddedFont); // 输出为字节数组,无需保存到硬盘 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { document.save(baos); return baos.toByteArray(); } } } }
注意事项
- 确认TTF字体允许嵌入,部分商用字体存在版权限制
setSubset(false)会嵌入完整字体,若需减小文件体积可设为true,不影响字体列表显示- 输入流由try-with-resources自动管理关闭,无需手动处理
二、使用OpenPDF实现
核心操作逻辑
- 用PdfReader读取源PDF,通过ByteArrayOutputStream输出修改后的内容
- 加载TTF字体时指定嵌入参数
- 将字体添加到PDF的AcroForm字体字典,无AcroForm则创建资源字典
代码示例
import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; public class OpenPdfFontEmbedder { public byte[] embedFontToPdf(byte[] sourcePdfBytes, InputStream ttfFontStream) throws Exception { // 加载源PDF到内存 PdfReader reader = new PdfReader(new ByteArrayInputStream(sourcePdfBytes)); try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 初始化PdfStamper用于修改PDF PdfStamper stamper = new PdfStamper(reader, baos); // 加载TTF字体并设置嵌入属性 BaseFont baseFont = BaseFont.createFont( "CustomEmbeddedFont", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, ttfFontStream.readAllBytes(), null ); // 将字体添加到PDF资源,确保字体列表可见 stamper.getAcroFields().addSubstitutionFont(baseFont); // 若PDF无表单字段,通过设置字体到内容流触发资源字典创建 if (stamper.getAcroFields().getFields().isEmpty()) { stamper.getWriter().getDirectContent().setFontAndSize(baseFont, 12); } // 完成修改并输出字节数组 stamper.close(); reader.close(); return baos.toByteArray(); } } }
注意事项
- OpenPDF的
BaseFont.createFont需传入字体字节数组,示例中直接读取输入流内容 - 添加替代字体是确保字体被嵌入到文档资源的关键步骤
- 无表单字段的PDF需手动触发资源字典创建,否则字体无法被注册
内容的提问来源于stack exchange,提问作者Schlomo Dumbo
相关产品推荐
相关产品推荐

