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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:25:31