如何让Apache FOP在PDF/A-2b中嵌入Base-14字体?
问题
使用Apache FOP v2.6生成嵌入Base-14字体的PDF/A-2b文件时,抛出org.apache.fop.pdf.PDFConformanceException异常,提示:
对于PDF/A-2b,所有字体(包括Base-14字体)都必须嵌入!违规字体:/Helvetica
相关代码片段如下:
import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import javax.xml.transform.TransformerException; import org.apache.fop.Version; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.FopFactoryBuilder; import org.apache.fop.configuration.ConfigurationException; import org.apache.fop.configuration.DefaultConfigurationBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PdfBuilder { private static final Logger LOG = LoggerFactory.getLogger(PdfBuilder.class); private static final FopFactory FOP_FACTORY; static { final var fopConfigXml = """ <fop version="1.0"> <renderers> <renderer mime="application/pdf"> <fonts> <auto-detect/> </fonts> </renderer> </renderers> </fop> """; final var fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI()); try { final var fopConfigStream = new ByteArrayInputStream(fopConfigXml.getBytes()); final var fopConfig = new DefaultConfigurationBuilder().build(fopConfigStream); fopFactoryBuilder.setConfiguration(fopConfig); LOG.info ("FOP Config.:" + " fopVersion={} xml.:{}{}", Version.getVersion(), "\n", fopConfigXml); } catch (final ConfigurationException e) { LOG.error("FOP Config Error.:" + " fopVersion={} xml.:{}{}", Version.getVersion(), "\n", fopConfigXml, e); } FOP_FACTORY = fopFactoryBuilder.build(); } public byte[] generatePDFfromFO(final byte[] bytesFO) throws IOException, FOPException, TransformerException { final var foUserAgent = FOP_FACTORY.newFOUserAgent(); foUserAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-2b"); : : : : return pdfBytes; } }
解决方案
问题核心是FOP默认不会自动嵌入Base-14字体,而PDF/A-2b要求所有字体必须嵌入,需补充以下配置:
方法一:修改XML配置文件
在FOP的XML配置中,添加强制嵌入Base-14字体的节点,同时可在配置中声明PDF/A模式(与代码设置二选一即可):
<fop version="1.0"> <renderers> <renderer mime="application/pdf"> <!-- 可选:也可通过代码设置pdf-a-mode --> <pdf-a-mode>PDF/A-2b</pdf-a-mode> <fonts> <auto-detect/> <!-- 关键配置:强制嵌入Base-14字体 --> <embed-base14-fonts>true</embed-base14-fonts> </fonts> </renderer> </renderers> </fop>
方法二:通过代码设置
如果不想修改XML配置,可在构建FopFactory时直接添加渲染器参数:
// 在fopFactoryBuilder.build()之前添加 fopFactoryBuilder.getRendererOptions().put("pdf-a-mode", "PDF/A-2b"); fopFactoryBuilder.getRendererOptions().put("embed-base14-fonts", true);
额外注意
- 确保FOP能访问到Base-14字体的物理文件,部分环境下需通过
<font-base>节点或fopFactoryBuilder.setFontBaseURL()指定字体路径 - 若同时在配置文件和代码中设置PDF/A模式,不会产生冲突,建议保持配置统一
内容的提问来源于stack exchange,提问作者Dave The Dane
相关产品推荐
相关产品推荐

