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

Apache FOP配置resources/fonts相对路径字体仍无法识别求助

解决Apache FOP相对路径加载Arial字体失败问题

我的字体存放路径为resources/fonts/Arial.ttf,已通过以下代码引用相对路径:

FontUris fontUris = new FontUris(Thread.currentThread().getContextClassLoader()
.getResource("fonts/Arial.ttf").toURI(), null);

fopFactoryBuilder.getFontManager().setResourceResolver(
ResourceResolverFactory.createDefaultInternalResourceResolver(fontUris.getEmbed()));

confInputStream = FopGenerator.class.getClassLoader().getResourceAsStream("fopconf.xconf");

fopFactoryBuilder.setConfiguration(new DefaultConfigurationBuilder().build(confInputStream));

对应的fopconf.xconf配置:

<?xml version="1.0" encoding="utf-8" ?>
<fop>
<strict-validation>false</strict-validation>
<base>.</base>
<font-base>./</font-base>
  <renderers>
    <renderer mime="application/pdf">
       <fonts>
        <font kerning="yes" embed-url="Arial.ttf" embedding-mode="subset">
             <font-triplet name="Arial" style="normal" weight="400"/>
        </font>
       </fonts>
    </renderer>
  </renderers>
</fop>

调试时确认fontUris中的嵌入URL已指向正确路径:/Users/midi/IdeaProjects/MyProject/forms/target/classes/fonts/Arial.ttf,但打印文档时仍收到警告:

org.apache.fop.apps.FOUserAgent          : Font "Arial,normal,400" not found. Substituting with "any,normal,400".

解决方法:

  • 调整配置加载与资源解析器的顺序
    FOP加载配置文件时会重置FontManager的部分配置,导致提前设置的ResourceResolver失效。需先加载配置,再设置ResourceResolver:

    // 先加载配置
    confInputStream = FopGenerator.class.getClassLoader().getResourceAsStream("fopconf.xconf");
    fopFactoryBuilder.setConfiguration(new DefaultConfigurationBuilder().build(confInputStream));
    
    // 再设置资源解析器
    FontUris fontUris = new FontUris(Thread.currentThread().getContextClassLoader()
    .getResource("fonts/Arial.ttf").toURI(), null);
    fopFactoryBuilder.getFontManager().setResourceResolver(
    ResourceResolverFactory.createDefaultInternalResourceResolver(fontUris.getEmbed()));
    
  • 修正配置文件中的字体路径
    由于字体位于classpath的fonts目录下,需修改font-base或直接指定完整的classpath路径:
    方案1:修改font-base为classpath路径

    <font-base>classpath:fonts/</font-base>
    <font kerning="yes" embed-url="Arial.ttf" embedding-mode="subset">
    

    方案2:直接在embed-url中指定classpath路径

    <font kerning="yes" embed-url="classpath:fonts/Arial.ttf" embedding-mode="subset">
    
  • 验证FO文件与配置的字体三元组匹配
    确保FO文档中引用的字体参数和配置里的<font-triplet>完全一致:

    • FO中需明确指定:font-family="Arial"、font-style="normal"、font-weight="400"
    • 避免拼写错误(比如Arial写成ArialMT,或大小写不匹配)
  • 备选:直接通过代码注册字体
    如果配置文件方式仍有问题,可跳过配置,直接在代码中注册字体:

    FontManager fontManager = fopFactoryBuilder.getFontManager();
    URI fontUri = Thread.currentThread().getContextClassLoader().getResource("fonts/Arial.ttf").toURI();
    fontManager.addFont(fontUri, true);
    

内容的提问来源于stack exchange,提问作者midi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:15:33