Linux 上的 PDFBox 2.0.17 字体

PDFBox 2.0.17 Fonts on Linux

我正在将 PDF 文档中的页面转换为字节,然后从中构建图像。

在 Windows 上,图像构建良好。在 Linux 上,图像上的字母看起来很脏(彼此重叠)

在日志 (weblogic) 中,我看到以下内容表明 Linux 上缺少所需的字体。

<Dec 3, 2019 11:06:35 PM EST> <Warning> <org.apache.pdfbox.pdmodel.font.PDType1Font> <BEA-000000> <Using fallback font LiberationSans for Helvetica-Bold>
<Dec 3, 2019 11:06:35 PM EST> <Warning> <org.apache.pdfbox.pdmodel.font.PDType1Font> <BEA-000000> <Using fallback font LiberationSans for Times-Roman>
<Dec 3, 2019 11:06:35 PM EST> <Warning> <org.apache.pdfbox.pdmodel.font.PDType1Font> <BEA-000000> <Using fallback font LiberationSans for Times-Bold>
<Dec 3, 2019 11:06:35 PM EST> <Warning> <org.apache.pdfbox.pdmodel.font.PDType1Font> <BEA-000000> <Using fallback font LiberationSans for Times-Italic>
<Dec 3, 2019 11:06:35 PM EST> <Warning> <org.apache.pdfbox.pdmodel.font.PDType1Font> <BEA-000000> <Using fallback font LiberationSans for Helvetica>

如何提供 Linux 上缺少的字体?我看到有关在 2 之前的版本上使用属性文件 (PDFBox_External_Fonts.properties) 的参考资料。我可以在 pdfbox 版本 2.0.17 上做什么?我找不到有关如何继续的任何文档。

PDFBox users mailing list 的 Tilman Hausherr 提供了帮助。

将所需字体复制到 {home}/.fonts 文件夹有助于解决我的问题。 PDFBox 代码在以下目录中查找字体。

protected String[] getSearchableDirectories()
{
     return new String[] { System.getProperty("user.home") + "/.fonts", // user
             "/usr/local/fonts", // local
             "/usr/local/share/fonts", // local shared
             "/usr/share/fonts", // system
             "/usr/X11R6/lib/X11/fonts" // X
     };
 }

Linux : org.apache.fontbox.util.autodetect.UnixFontDirFinder.java
Windows : org.apache.fontbox.util.autodetect.WindowsFontsDirFinder.Java
PDFBox通过上面类加载系统的字体。你可以查看来源。
解决方案一:可以将缺少的字体添加到任意目录,然后在上面添加find Dir 类
解决方案 2 :正如您提到的 Tilman Hausher 的解决方案。

还有一件事:当 PDFBox 第一次加载系统中的所有字体时。然后创建一个名为 .pdfbox.cache 的文件。如果您想要 PDFBox 重新加载字体或加载新添加的字体,您需要先删除该文件。如果有任何问题,请告诉我。

我写这篇文章是为了那些可能遇到与 OP 相同的问题但在 Microsoft-Azure 上的 Linux WebApps 安装上使用 PdfBox 的人。我还提供了@user1187958 和@Lux 的回答中未提供的更多信息 - 我对此表示感谢,因为他们帮助我解决了我的问题。

如@user1187958 所说,可以将字体安装在 PDFBox 搜索的目录之一中(通过以下代码)

package org.apache.fontbox.util.autodetect;

public class UnixFontDirFinder extends NativeFontDirFinder
{
    protected String[] getSearchableDirectories() {
        return new String[] { System.getProperty("user.home") + "/.fonts", "/usr/local/fonts", "/usr/local/share/fonts", "/usr/share/fonts", "/usr/X11R6/lib/X11/fonts"};
    }
}

然而,问题是所有这些目录(据我所知)在服务器重启期间被 Azure 删除了。事实上,您显然需要为 PDFBox 重新启动服务器以注册字体已上传。所以我所做的——尽管我想有更好的方法——是从 PDFBox.jar 中提取 org.apache.fontbox.util.autodetect.UnixFontDirFinder,反编译它,添加我自己的目录(按照下面的代码提取),然后将它插入回去进入.jar

 package org.apache.fontbox.util.autodetect;

public class UnixFontDirFinder extends NativeFontDirFinder
{
    protected String[] getSearchableDirectories() {
        return new String[] { System.getProperty("user.home") + "/.fonts", "/usr/local/fonts", "/usr/local/share/fonts", "/usr/share/fonts", "/usr/X11R6/lib/X11/fonts" 
,"/home/site/wwwroot/webapps/myapp/fonts"};
    }
}

上传新的 .jar 后,我将必要的字体上传到目录 /home/site/wwwroot/webapps/myapp/fonts,重新启动服务器,它成功了。

请注意,根据 org.apache.fontbox.util.autodetect.FileFinder.java 中的以下代码:

,上传的字体必须是以下格式之一 .ttf、.otf、.pfb、.ttc
private boolean checkFontfile(final File file) {
        final String name = file.getName().toLowerCase(Locale.US);
        return (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".pfb") || name.endsWith(".ttc")) && !name.startsWith("fonts.");
    }

C:/Windows/Fonts 目录上传 TTF 文件可以,但需要检查此操作的合法性。