我需要使用Apache FOP后端将一个docx文档导出到Ubuntu服务器上的PDF/A-1b。
该文件并不花哨,它使用了基本的windows字体Calibri,Courier New,Times New Roman,Symbol,Wingdings。PDF/A-1b配置文件要求嵌入所有字体,包括标准的base-14字体,因此我从/usr/share/ fonts / Type1 /urw-base35中提取了ubuntuType1字体,并且在/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缓存,但这些操作都没有解决问题。
有什么办法解决这个问题吗?
发布于 2021-05-26 06:08:50
在浪费了两天多的时间后找到的。出于某种原因,该元素必须以方案作为前缀:
<font-base>file:/home/luca/Desktop/ubuntufonts/</font-base>现在,我也想为未来沮丧的读者指出,实际上没有理由使用Type1字体来映射Base14字体,所以帮你自己一个忙,使用OTF字体来映射它们(在我的Ubuntu上,他们在/usr/share/fonts/opentype/urw-base35),所以没有必要额外的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>classpath:/fonts/</font-base>,并在/src/main/resources/fonts/下添加字体文件。
https://stackoverflow.com/questions/67693639
复制相似问题