当前位置: 首页 > 知识库问答 >
问题:

Docx4j导出为PDF/A-1b-base14字体嵌入

吕岳
2023-03-14

我需要使用Apache FOP后端将docx文档导出到Ubuntu服务器上的PDF/1b。

该文档没有什么花哨的,它使用基本的窗口字体Calibri,Courier New,Times New Roman,Symbol,Wingdings。PDF/A-1b 配置文件需要嵌入所有字体,包括标准的 base-14 字体,所以我从 /usr/share/fonts/type1/urw-base35 中提取了 Ubuntu Type1 字体,我在 /home/luca/Desktop/ubuntufonts/ 路径中有 14 个 .pfb 和 14 个 .afm 文件

我认为我设置的一切都是正确的,但是启用A-1b配置文件会导致以下异常:

Caused by: java.io.FileNotFoundException: Neither an AFM nor a PFM file was found for NimbusRoman-BoldItalic.pfb
    at org.apache.fop.fonts.type1.Type1FontLoader.read(Type1FontLoader.java:147)
    at org.apache.fop.fonts.FontLoader.getFont(FontLoader.java:126)
    at org.apache.fop.fonts.FontLoader.loadFont(FontLoader.java:110)
    at org.apache.fop.fonts.LazyFont.load(LazyFont.java:119)
...
 Caused by: java.lang.RuntimeException: Failed to read font file NimbusRoman-BoldItalic.pfb
    at org.apache.fop.fonts.LazyFont.load(LazyFont.java:132)
    at org.apache.fop.fonts.LazyFont.hasChar(LazyFont.java:179)
    at org.apache.fop.fonts.Font.hasChar(Font.java:278)
    at org.apache.fop.fonts.FontSelector.selectFontForCharacter(FontSelector.java:47)
    at org.apache.fop.fonts.FontSelector.selectFontForCharacterInText(FontSelector.java:85)
    at org.apache.fop.layoutmgr.inline.TextLayoutManager.initialize(TextLayoutManager.java:162)
    at org.apache.fop.layoutmgr.AbstractLayoutManager.getChildLM(AbstractLayoutManager.java:118)

但是文件就在那里:

luca@luca-vm:~/Desktop/ubuntufonts$ ls
D050000L.afm                 NimbusRoman-Italic.afm
D050000L.pfb                 NimbusRoman-Italic.pfb
NimbusMonoPS-Bold.afm        NimbusRoman-Regular.afm
NimbusMonoPS-BoldItalic.afm  NimbusRoman-Regular.pfb
NimbusMonoPS-BoldItalic.pfb  NimbusSans-Bold.afm
NimbusMonoPS-Bold.pfb        NimbusSans-BoldItalic.afm
NimbusMonoPS-Italic.afm      NimbusSans-BoldItalic.pfb
NimbusMonoPS-Italic.pfb      NimbusSans-Bold.pfb
NimbusMonoPS-Regular.afm     NimbusSans-Italic.afm
NimbusMonoPS-Regular.pfb     NimbusSans-Italic.pfb
NimbusRoman-Bold.afm         NimbusSans-Regular.afm
NimbusRoman-BoldItalic.afm   NimbusSans-Regular.pfb
NimbusRoman-BoldItalic.pfb   StandardSymbolsPS.afm
NimbusRoman-Bold.pfb         StandardSymbolsPS.pfb

通过web搜索,似乎应该创建一个fop.xml配置文件,将字体名称映射到我提取的文件。这是我准备的文件:

<fop version="1.0">
    <font-base>/home/luca/Desktop/ubuntufonts/</font-base>
    <renderers>
        <renderer mime="application/pdf">
            <fonts>
                <font embed-url="NimbusSans-Regular.pfb" embedding-mode="full">
                    <font-triplet name="Helvetica" style="normal" weight="normal" />
                    <font-triplet name="Calibri" style="normal" weight="normal" />
                </font>
                <font embed-url="NimbusSans-Bold.pfb" embedding-mode="full">
                    <font-triplet name="Helvetica" style="normal" weight="bold" />
                    <font-triplet name="Calibri" style="normal" weight="bold" />
                </font>
                <font embed-url="NimbusSans-Italic.pfb" embedding-mode="full">
                    <font-triplet name="Helvetica" style="italic" weight="normal" />
                    <font-triplet name="Calibri" style="italic" weight="normal" />
                </font>
                <font embed-url="NimbusSans-BoldItalic.pfb" embedding-mode="full">
                    <font-triplet name="Helvetica" style="italic" weight="bold" />
                    <font-triplet name="Calibri" style="italic" weight="bold" />
                </font>

                <font embed-url="NimbusRoman-Regular.pfb" embedding-mode="full">
                    <font-triplet name="Times" style="normal" weight="normal" />
                    <font-triplet name="Times New Roman" style="normal" weight="normal" />
                </font>
                <font embed-url="NimbusRoman-Bold.pfb" embedding-mode="full">
                    <font-triplet name="Times" style="normal" weight="bold" />
                    <font-triplet name="Times New Roman" style="normal" weight="normal" />
                </font>
                <font embed-url="NimbusRoman-Italic.pfb" embedding-mode="full">
                    <font-triplet name="Times" style="italic" weight="normal" />
                    <font-triplet name="Times New Roman" style="normal" weight="normal" />
                </font>
                <font embed-url="NimbusRoman-BoldItalic.pfb" embedding-mode="full">
                    <font-triplet name="Times" style="italic" weight="bold" />
                    <font-triplet name="Times New Roman" style="normal" weight="normal" />
                </font>

                <font embed-url="NimbusMonoPS-Regular.pfb" embedding-mode="full">
                    <font-triplet name="Courier" style="normal" weight="normal" />
                    <font-triplet name="Courier New" style="normal" weight="normal" />
                </font>
                <font embed-url="NimbusMonoPS-Bold.pfb" embedding-mode="full">
                    <font-triplet name="Courier" style="normal" weight="bold" />
                    <font-triplet name="Courier New" style="normal" weight="bold" />
                </font>
                <font embed-url="NimbusMonoPS-Italic.pfb" embedding-mode="full">
                    <font-triplet name="Courier" style="italic" weight="normal" />
                    <font-triplet name="Courier New" style="italic" weight="normal" />
                </font>
                <font embed-url="NimbusMonoPS-BoldItalic.pfb" embedding-mode="full">
                    <font-triplet name="Courier" style="italic" weight="bold" />
                    <font-triplet name="Courier New" style="italic" weight="bold" />
                </font>

                <font embed-url="StandardSymbolsPS.pfb" embedding-mode="full">
                    <font-triplet name="Symbol" style="normal" weight="normal" />
                    <font-triplet name="Symbol" style="normal" weight="bold" />
                </font>

                <font embed-url="D050000L.pfb" embedding-mode="full">
                    <font-triplet name="ZapfDingbats" style="normal" weight="normal" />
                    <font-triplet name="ZapfDingbats" style="normal" weight="bold" />
                </font>
            </fonts>
        </renderer>
    </renderers>
</fop>

这是我使用的最终转换代码:

        // Document loading (required)
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(classPathResource.getFile());

        // Set up font mapper (optional)
        Mapper fontMapper = new IdentityPlusMapper();
        wordMLPackage.setFontMapper(fontMapper);

        // FO exporter setup (required)
        // .. the FOSettings object
        String fopConfig = Files.readString(new ClassPathResource("fop.xml").getFile().toPath());
        FOSettings foSettings = Docx4J.createFOSettings();
        foSettings.setApacheFopConfiguration(fopConfig);
        foSettings.setOpcPackage(wordMLPackage);

        FOUserAgent foUserAgent = FORendererApacheFOP.getFOUserAgent(foSettings);
        foUserAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");

        // PDF/A-1a, PDF/A-2a and PDF/A-3a require accessibility to be enabled
        // see further https://stackoverflow.com/a/54587413/1031689
        foUserAgent.setAccessibility(true); // suppress "missing language information" messages from FOUserAgent .processEvent

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

        // Clean up, so any ObfuscatedFontPart temp files can be deleted 
        if (wordMLPackage.getMainDocumentPart().getFontTablePart()!=null) {
            wordMLPackage.getMainDocumentPart().getFontTablePart().deleteEmbeddedFontTempFiles();
        }       
        // This would also do it, via finalize() methods
        foSettings = null;
        wordMLPackage = null;

我还尝试将文档字体直接嵌入到Word文档中,并在各种尝试之间删除fop缓存,但这些操作并未解决问题。

知道如何解决这个问题吗?

共有1个答案

游勇军
2023-03-14

在上面浪费了两天多的时间,终于找到了。由于某种原因,元素必须以scheme为前缀:

<font-base>file:/home/luca/Desktop/ubuntufonts/</font-base>

现在,我还想为未来沮丧的读者指出,实际上没有理由使用Type1字体来映射Base14字体,所以帮自己一个忙,使用OTF字体来映射它们(在我的Ubuntu vm上,它们位于< code >/usr/share/fonts/opentype/urw-base 35 ),所以没有必要进行额外的AFM/PFM文件查找。

这是我最后的xml配置文件:

<fop version="1.0">
    <font-base>file:/home/luca/Desktop/ubuntuttf/</font-base>
    <use-cache>false</use-cache>
    <strict-configuration>true</strict-configuration>
    <renderers>
        <renderer mime="application/pdf">
            <fonts>
                <font embed-url="NimbusSans-Regular.otf">
                    <font-triplet name="Helvetica" style="normal" weight="normal" />
                    <font-triplet name="Calibri" style="normal" weight="normal" />
                    <font-triplet name="sans-serif" style="normal" weight="normal"/>
                    <font-triplet name="SansSerif" style="normal" weight="normal"/>
                </font>
                <font embed-url="NimbusSans-Bold.otf">
                    <font-triplet name="Helvetica" style="normal" weight="bold" />
                    <font-triplet name="Calibri" style="normal" weight="bold" />
                    <font-triplet name="sans-serif" style="normal" weight="bold"/>
                    <font-triplet name="SansSerif" style="normal" weight="bold"/>
                </font>
                <font embed-url="NimbusSans-Italic.otf">
                    <font-triplet name="Helvetica" style="italic" weight="normal" />
                    <font-triplet name="Calibri" style="italic" weight="normal" />
                    <font-triplet name="sans-serif" style="italic" weight="normal"/>
                    <font-triplet name="SansSerif" style="italic" weight="normal"/>
                </font>
                <font embed-url="NimbusSans-BoldItalic.otf">
                    <font-triplet name="Helvetica" style="italic" weight="bold" />
                    <font-triplet name="Calibri" style="italic" weight="bold" />
                    <font-triplet name="sans-serif" style="italic" weight="bold"/>
                    <font-triplet name="SansSerif" style="italic" weight="bold"/>
                </font>
    
                <font embed-url="NimbusRoman-Regular.otf">
                    <font-triplet name="Times" style="normal" weight="normal" />
                    <font-triplet name="Times New Roman" style="normal" weight="normal" />
                    <font-triplet name="serif" style="normal" weight="normal"/>
                    <font-triplet name="any" style="normal" weight="normal"/>
                </font>
                <font embed-url="NimbusRoman-Bold.otf">
                    <font-triplet name="Times" style="normal" weight="bold" />
                    <font-triplet name="Times New Roman" style="normal" weight="bold" />
                    <font-triplet name="serif" style="normal" weight="bold"/>
                    <font-triplet name="any" style="normal" weight="bold"/>
                </font>
                <font embed-url="NimbusRoman-Italic.otf">
                    <font-triplet name="Times" style="italic" weight="normal" />
                    <font-triplet name="Times New Roman" style="italic" weight="normal" />
                    <font-triplet name="serif" style="italic" weight="normal"/>
                    <font-triplet name="any" style="italic" weight="normal"/>
                </font>
                <font embed-url="NimbusRoman-BoldItalic.otf">
                    <font-triplet name="Times" style="italic" weight="bold" />
                    <font-triplet name="Times New Roman" style="italic" weight="bold" />
                    <font-triplet name="serif" style="italic" weight="bold"/>
                    <font-triplet name="any" style="italic" weight="bold"/>
                </font>
    
                <font embed-url="NimbusMonoPS-Regular.otf">
                    <font-triplet name="Courier" style="normal" weight="normal" />
                    <font-triplet name="Courier New" style="normal" weight="normal" />
                    <font-triplet name="monospace" style="normal" weight="normal"/>
                </font>
                <font embed-url="NimbusMonoPS-Italic.otf">
                    <font-triplet name="Courier" style="normal" weight="bold" />
                    <font-triplet name="Courier New" style="normal" weight="bold" />
                    <font-triplet name="monospace" style="normal" weight="bold"/>
                </font>
                <font embed-url="NimbusMonoPS-Bold.otf">
                    <font-triplet name="Courier" style="italic" weight="normal" />
                    <font-triplet name="Courier New" style="italic" weight="normal" />
                    <font-triplet name="monospace" style="italic" weight="normal"/>
                </font>
                <font embed-url="NimbusMonoPS-BoldItalic.otf">
                    <font-triplet name="Courier" style="italic" weight="bold" />
                    <font-triplet name="Courier New" style="italic" weight="bold" />
                    <font-triplet name="monospace" style="italic" weight="bold"/>
                </font>
    
                <font embed-url="StandardSymbolsPS.otf">
                    <font-triplet name="Symbol" style="normal" weight="normal" />
                    <font-triplet name="Symbol" style="normal" weight="bold" />
                </font>
    
                <font embed-url="D050000L.otf">
                    <font-triplet name="ZapfDingbats" style="normal" weight="normal" />
                    <font-triplet name="ZapfDingbats" style="normal" weight="bold" />
                </font>
            </fonts>
        </renderer>
    </renderers>
</fop>

另外,如果有人对将字体嵌入jar/war档案感兴趣,只需将font-base元素改为< code >

 类似资料:
  • 我正在使用FOP 0.94,我也许可以升级到FOP 0.95。是否可以嵌入Bas14字体?如果可以,如何? 我试过把这个放在fop.xconf里: 那行不通。 最好的问候,莫滕

  • 在jasper-report中生成PDF/A包含许多缺陷,并且在某些版本的jasper-report中不受支持。这就是为什么我决定传递这篇问答文章的原因,它指出了将一个带有图形的简单报表导出到PDF/a所必需的步骤和库版本 示例数据(usersrep.csv) 如果将报告导出为pdf,我需要做什么来生成pdf/A-1A?

  • 我正在使用PoDoFo库生成一个PDF文档。嵌入了除Base14字体(“快递”、“Helvetica”、“时代”、“符号”、“ZapfDingbats”)之外的所有字体。如何嵌入这4种Base14字体?

  • 我正在尝试将字体嵌入到我的pdf/a中。 我找到了很多答案,但使用的是iTextSharp 在我的cas中,我使用iText7,但我所尝试的都是错误的: “所有字体都必须嵌入……” 我有一个ttf文件为我的字体,但我没有找到一种方法嵌入到我的pdf使用它... 有人能帮我吗? 事先谢谢 kor6k

  • 问题内容: 我有一个使用Foxit表单设计器创建的pdf文件。在我的设计系统上,我安装了条形码字体。条形码字体在AcroField之一中使用。foxit似乎没有在文档中嵌入字体。 我也有一些客户的计算机上未安装条形码字体,因此我想将该字体嵌入到PDF中。我是否可以使用iText将AcroFields中使用的字体嵌入到PDF中? 编辑: 字体似乎包含在文本中,但没有包含在字段中,因此字体(条形码)将

  • 如果我在MS Word中保存了带有嵌入字体选项的DOCX文件,我可以在linux中的libreoffice writer gui中打开它,看到它带有linux上没有安装的原始字体。 我也可以从libreoffice writer菜单按钮和嵌入在文件中的字体导出到PDF,它在任何电脑上都很好看。 提前致谢