谷歌网络字体和使用wkhtmltopdf从HTML生成PDF

72
我正在使用wkhtmltopdf将HTML文件转换为PDF格式;它的效果非常出色,可以完全按照WebKit的方式呈现PDF页面。
我正在使用Google Web Fonts让用户能够自定义文档的外观,提供了几种字体供选择。在浏览器中也可以很好地运行。
问题是,在使用wkhtmltopdf将这些HTML文件转换为PDF时,无法加载Google Fonts。我看到其他人也遇到了相同的问题
请问有谁能帮我解决这个问题吗?
编辑:直接在CSS中声明@font-face也不起作用。
10个回答

58

使用wkhtmltopdf将HTML转换为PDF时,应尽量避免使用woff字体。使用Google Web Fontstruetype格式并进行base64编码。

最近我尝试从Google Web Fonts中使用字体。在浏览器中显示正确,但在将HTML转换为PDF之后却无法显示。

在广泛搜索网络后,我终于找到了将字体编码为base64格式并获得@font-face CSS的工具。

阅读解决方案请点击这里


2
+1。请注意:如链接解决方案页面上的评论所述,该方法似乎不适用于OS X(10.9),但在Linux下有效。 - Pepijn Olivier
它在Windows上运行良好,并且还可以使用wkhtmltopdf的节点包装器。 - rjreed
这仍然无法使用紧凑字体(如Roboto Condensed)与已修补的QT版本的wkhtmltopdf-binary 0.12.3.1一起工作。也许是由于持续的字距错误引起的..? - genkilabs
2
你能更新一下链接吗?自上个月以来,该页面已不存在。 - Jeroen van Veghel
如果仍然无法正常工作,请将字体转换为base64字符串! - headkit

43

一种简单的解决方案:将字体进行Base64编码并嵌入CSS中:

@font-face {
    font-family: 'OpenSans';
    src: url(data:font/truetype;charset=utf-8;base64,AAEAAAATAQA...
}

通过Webfont Generator的高级选项,FontSquirrel 可以为您完成此操作;Google 和其他字体可以使用此工具进行编码。

我已经在pdfkitwicked_pdf中使用了此解决方案,它们通过wkhtmltopdf工作,因此我认为这应该也适用于本地的wkhtmltopdf


3
我可以确认这对我有效,但是我必须使用OS X的v0.10.0-rc2版wkhtmltopdf。最新版本在这方面对我不起作用。 - MetaSkills
1
@MetaSkills 谢谢你提到这个问题 - 我也遇到了同样的问题,而且排查起来非常麻烦。在OSX上运行版本为0.12.3的wkhtmltopdf时,无法与自定义字体配合使用,但在我们的Ubuntu测试和生产服务器上似乎可以正常工作。 - Topher Hunt
@Topher Hunt 很高兴看到你的评论,我也在OSX上遇到了同样的问题,字体无法工作,但是当部署到Ubuntu服务器时就可以了。 - HastingsDirect

14

我曾经遇到过同样的问题,并通过下载字体并使用以下font-face声明在本地文件上运行它来解决:

@font-face {
    font-family: 'PT Sans';
    src: url( '/public/inc/fonts/PTS55F-webfont.eot');
    src: url( '/public/inc/fonts/PTS55F-webfont.eot?#iefix') format('embedded-opentype'),
         url( '/public/inc/fonts/PTS55F-webfont.woff') format('woff'),
         url( '/public/inc/fonts/PTS55F-webfont.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;
}

我在字体松鼠上找到了这种字体,但你的情况可能会有所不同。

我认为,谷歌提供的字体只加载它认为该浏览器需要的格式,对于WebKit来说这个格式是woff(我相信)。但wkhtmltopdf不能在PDF中嵌入woff字体,因此默认使用sans-serif。通过声明所有字体,TrueType字体被包含在其中,这就是PDF实际使用的字体类型。

还有,你需要将要使用的字体定义为任何font-family CSS定义中的第一个,否则wkhtmltopdf将会忽略它。


1
好的解释。如果您访问GWF网站并下载字体的zip文件,它包含TTF文件,wkhtmltopdf可以处理。但我不确定GWF上的所有字体是否都包含TTF。 - mmalone
非常感谢!我个人通过在计算机的X11服务器上安装字体(它们可以从存储库下载)找到了解决方法。 - Mathieu Rodic
如果有人像我一样通过Google Fonts API搜索PISA PDF HTML Django问题,请查看此链接:http://xhtml2pdf.appspot.com/static/pisa-en.html 并只使用ttf文件。 - andilabs
关于 PISA 的另一个注记(你会笑的),在 CSS 中链接字体有一个重要问题。例如,在开发服务器上,通过链接到静态文件可以正常工作,但在生产环境中为了使其正常工作,您必须不通过 HTTP 链接而是链接到本地文件,因此例如使用 MEDIA_ROOT 来实现这个目的。 - andilabs

12

我刚刚测试了使用@import标记符的方法是可行的:

<style>
@import 'https://fonts.googleapis.com/css?family=Montserrat';
</style>

我正在使用django-wkhtmltopdf 2.0.3版本

更新:在django-wkhtmltopdf 3.3.0版本中仍然有效


这实际上是最好的“解决方法”。在我看来,这甚至不是一种变通方法,而是使用gfont和wkhtmltopdf的最清洁的方式。谢谢。 - JFC

3

我已经为此苦苦挣扎了两天,如果以上任何答案都对你无效,我的建议是:

在托管 Web 服务器的计算机上安装字体(ttf),并像普通字体一样在 CSS 中引用它。

body{
    font-family: 'Lato';
}

现在,wkhtmltopdf 应该能够包含字体了。

由于他允许用户根据可用的Google字体选择他们想要使用的字体,这可能意味着安装越来越多的字体。 - gdvalderrama
谢谢。我尝试了其他一些答案,将一些巨大的base64编码字体字符串嵌入到我的代码中,但我认为这不是一个好主意。最后,我安装了我需要的字体,因为我不需要太多的字体。 - Kenshin
请问您能否提供更多关于如何包含它的细节呢?例如,src: {{ public_path('fonts/noto-sans.regular.ttf') }}; 您是如何导入它的呢? - Pathros

2

我一定尝试了无数种方式才使其生效(从本地)。 我正在尝试通过WKHtmlToPdf将Open Sans Condensed嵌入到pdf中。

我认为重要的是直接从谷歌下载和安装Open Sans Condensed ttf并进行安装。 安装后重新启动以允许其他服务访问非常重要。 我最初从font-squirrel下载了ttf,压缩后在windows / fonts中列为“Open Sans”,这是错误的。 如果您在google安装后查看,它将列为“Open Sans Condensed Light”,因此即使是谷歌的local('Open Sans Cond Light')脚本也是错误的。

正如之前提到的,您需要明确拉伸和重量,这就是对我有效的方法:

    @font-face { 
     font-family: 'Open Sans'; 
     font-style: normal; 
     font-weight: 400; 
     src: local('Open Sans');
    }

    @font-face { 
     font-family: 'Open Sans Condensed'; 
     font-stretch:condensed; 
     font-style: normal; 
     font-weight: 300; 
     src: local('Open Sans Condensed Light');
    }

@@font-face { font-family: 'Open Sans Condensed Bold'; font-stretch:condensed; font-style: normal; font-weight: 700; src: local('Open Sans Condensed'), local('Open Sans Condensed Bold');}

2
以下内容对我有效。请注意包含扩展字符集(如果需要):
```

以下内容对我有效。请注意包含扩展字符集(如果需要):

```
<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,600&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese);
</style>

2
在我的情况下,我只需要添加这个选项。
--javascript-delay 1000

并且 Google 字体的文本开始展示。

[wkhtmltopdf 0.12.4 (带有补丁的 QT 版本)]


1
使用 @import 对于让 Google Fonts 在 wkhtmltopdf 中工作至关重要,但是我遇到了CJK(中文、日语和韩语)字符不显示的问题。解决方案是切换到 Google Font API 的第二版(https://fonts.googleapis.com/css2)。
以下是我插入到我的 HTML 中的代码片段,以获取通过测试 PDF 需要支持的所有语言。请注意加载数十个远程字体的性能影响。
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans";
[lang="sq"] {font-family: 'Noto Sans', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic";
[lang="ar"] {font-family: 'Noto Sans Arabic', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Bengali";
[lang="bn"] {font-family: 'Noto Sans Bengali', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Georgian";
[lang="ka"] {font-family: 'Noto Sans Georgian', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Gujarati";
[lang="gu"] {font-family: 'Noto Sans Gujarati', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew";
[lang="he"] {font-family: 'Noto Sans Hebrew', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari";
[lang="hi"] {font-family: 'Noto Sans Devanagari', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Serif+Tibetan";
[lang="bo"] {font-family: 'Noto Serif Tibetan', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Gurmukhi";
[lang="pa"] {font-family: 'Noto Sans Gurmukhi', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Nastaliq+Urdu";
[lang="ur"] {font-family: 'Noto Nastaliq Urdu', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Tai+Viet";
[lang="vi"] {font-family: 'Noto Sans Tai Viet', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+SC";
[lang="zh-hans"] {font-family: 'Noto Sans SC', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+TC";
[lang="zh-hant"] {font-family: 'Noto Sans TC', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+JP";
[lang="ja"] {font-family: 'Noto Sans JP', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+KR";
[lang="ko"] {font-family: 'Noto Sans KR', sans-serif !important;}
</style>

1

请确保您在打印样式表中不声明要使用的字体。


我使用每个文档一个样式表时遇到了这个问题。 - Mathieu Rodic
进行了一些测试,发现唯一能够使网络字体打印的方法是在CSS中声明完整的@font-face代码,尽管Firefox 3.6.13的支持似乎不太稳定(有时会打印,有时则不会),但在其他所有浏览器中都可以正常工作。因此,请继续从Google的自动嵌入式CSS中获取@font-face代码,并将其直接添加到您的CSS中并尝试使用。 - Andres Ilich
尝试在更新的浏览器中打印此内容,例如FF4或Chrome,http://fiddle.jshell.net/WZYmq/show/ - Andres Ilich
从Web浏览器打印完美无缺。如先前所述,导致麻烦的是使用wkhtmltopdf生成PDF。 - Mathieu Rodic
你认为在你的环境中可能会有其他解决方案吗?例如cute pdf writer - Andres Ilich
我选择了这个命令行工具在Linux服务器上自动将HTML页面转换为PDF...而Cute PDF无法做到。感谢您的帮助。 - Mathieu Rodic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接