问题 邪恶的PDF +字体+ heroku + rails3.2


我在用着 wicked_pdf 使用rails 3.2.11和ruby 1.9.3从HTML生成PDF并部署到Heroku。

我的pdf.css.scss.erb:

<% app_fullhost = Constants["app_fullhost"] %>

@font-face {
  font-family:'DosisMedium'; font-style:normal; font-weight:500;
  src: url(<%=app_fullhost%>/app/font/dosis/Dosis-Medium.ttf) format('woff');
}

*, body {
  font-family: "DosisLight", 'Times New Roman', 'Arial', sans-serif;
} 

哪里 app_fullhost 是开发或生产中的确切主机。

我的pdf布局包括:

%html{:lang => I18n.locale}
  %head
    %meta{:charset => "utf-8"}
    %title= content_for?(:title) ? yield(:title) : Settings.app_name
    = wicked_pdf_stylesheet_link_tag "pdf"

在production.rb我有

config.assets.precompile +=%w(pdf.css)

这在开发中没有问题,但在Heroku上,pdf文件不会加载所需的字体。我也尝试过不同的解决方案,比如在production.rb中添加这些解决方案:

config.assets.paths << "#{Rails.root}/app/assets/fonts"
config.assets.precompile += %w(*.svg *.eot *.woff *.ttf) 
config.assets.precompile += %w(.svg .eot .woff .ttf) 

我也尝试改变(在pdf.css.scss.erb中):

@font-face {
  font-family:'Dosis'; font-style:normal; font-weight:500;
  src: url('Dosis-Medium.ttf') format('woff');
}

要么

@font-face {
  font-family:'Dosis'; font-style:normal; font-weight:500;
  src: url(<%= asset_path('Dosis-Medium.ttf')%>) format('woff');
}

字体在 assets/fonts 还有 public/app/font/dosis 和Heroku上的网址正确响应:

..//myapp/app/font/dosis/Dosis-Medium.ttf" and 
..//myapp/assets/Dosis-Medium.ttf 

如何在Heroku上加载字体?


1015
2018-02-06 16:47


起源



答案:


wkhtmltopdf,该计划的基础 wicked_pdf,在通过CSS加载字体方面是出了名的时髦。在某些系统上,它使用绝对路径,有时需要相对路径。即使你正确地获得了路径,它也可能因不准确的CSS减速等而被抛弃。仅仅在SO上就有很多问题。

我发现的最好,最灵活和最便携的解决方案是对您尝试使用的字体进行Base64编码,并将其直接包含在CSS文件中:

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

9
2017-07-18 00:33



这绝对有效,我唯一的补充就是使用 字体Squirell发生器 获取Base64数据。 - Bjorn Forsberg
我链接的原始网站资源已脱机。您可以使用Font Squirrel或 这个工具 如果您使用的是非Font Squirrel字体。 - Arman H
您是否遇到过多个Base64编码的警告 @font-face 一个文件中的条目? - James Chevalier
@JamesChevalier:没有任何警告,你可以使用多个字体嵌入到单个样式表中而没有任何问题。 - Arman H
我需要将哪种字体转换为Base64 - eot,wott,ttf ..我一直看到这个问题的类似答案,但没有人澄清,由于某种原因,这个解决方案对我不起作用。谢谢。 - VelLes


答案:


wkhtmltopdf,该计划的基础 wicked_pdf,在通过CSS加载字体方面是出了名的时髦。在某些系统上,它使用绝对路径,有时需要相对路径。即使你正确地获得了路径,它也可能因不准确的CSS减速等而被抛弃。仅仅在SO上就有很多问题。

我发现的最好,最灵活和最便携的解决方案是对您尝试使用的字体进行Base64编码,并将其直接包含在CSS文件中:

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

9
2017-07-18 00:33



这绝对有效,我唯一的补充就是使用 字体Squirell发生器 获取Base64数据。 - Bjorn Forsberg
我链接的原始网站资源已脱机。您可以使用Font Squirrel或 这个工具 如果您使用的是非Font Squirrel字体。 - Arman H
您是否遇到过多个Base64编码的警告 @font-face 一个文件中的条目? - James Chevalier
@JamesChevalier:没有任何警告,你可以使用多个字体嵌入到单个样式表中而没有任何问题。 - Arman H
我需要将哪种字体转换为Base64 - eot,wott,ttf ..我一直看到这个问题的类似答案,但没有人澄清,由于某种原因,这个解决方案对我不起作用。谢谢。 - VelLes


我遇到了这个问题并遵循了Arman H概述的建议 - 我将字体转换为base 64并直接在CSS / SCSS文件中引用它。我遵循的其余步骤与原始问题中概述的步骤非常相似。

我在这里整理了一个完整的描述(带有源代码的github链接): http://apleroy.com/posts/custom-pdf-fonts-with-wicked_pdf-and-heroku

首先,我引用了字体目录中的字体。

<%# /fonts/custom_fonts.css.scss.erb %>
@font-face {
    font-family: "SourceSansPro-Light";
    src: url('<%= asset_path("SourceSansPro-Light.otf") %>');
}

然后,基于64编码字体,我使用了这个网站(已经在上面的评论中提到): http://www.opinionatedgeek.com/dotnet/tools/base64encode/。 base-64编码输出是一个随机字符串,是几百行字母数字字符。我将此输出复制到新的pdf.css.scss文件中:

<%# /stylesheets/pdf.css.scss %>
@font-face {
  font-family: 'Source Sans Pro Light';
  src: url(data:font/truetype;charset=utf-8;base64,T1RUTw-----THIS IS HUNDREDS OF LINES LONG -------sGAnBSvO7nBqXQ==)
}

在实际的html页面(转换为PDF)中,我使用wicked_pdf样式表标记进行了引用 - 如原始问题中所述:

<%# views/pdf_pages/show.html.erb %>
<meta charset='utf-8' />
<%= wicked_pdf_stylesheet_link_tag "pdf" %>

最后,我预编译了pdf样式表,以便将其包含在资产管道中,以便在Heroku上进行部署:

#application.rb
config.assets.precompile += ['pdf.css']

3
2018-06-18 18:45



欢迎来到Stackoverflow。你能否将答案的主要部分放入文本而不是链接?将来找到它会容易得多 - slfan
我刚刚在相关信息中添加了。谢谢你的帮助。 - apleroy


让我看看我是否有这个权利:

服务器1:构建PDF,需要字体,并从URL中提取它们 这在dev中本地工作,但不在heroku上。

日志中有什么东西吗? (你看到字体的http请求吗?)

你说它没有加载正确的字体。它是否爆炸,或者只是渲染,好像它从未加载过字体(例如字体提取上的404)。

如果你不从heroku中提取字体文件,这是否有效? (比如使用aws或其他URL中的其他字体作为测试)

您是否从当前正在运行的同一服务器进程中提取? 您是否有多个dyno或多个独角兽进程可以处理当前进程(构建pdf)和传入请求(提供字体文件)

我见过人们只运行一个dyno,但尝试运行两个http事件,并遇到问题。如果你只有一个dyno(你没有提到其他),添加另一个dyno,看看会发生什么,或者添加另一个unicorn进程。


1
2018-05-08 20:22