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

时间:2013-02-06 16:47:12

标签: heroku fonts ruby-on-rails-3.2 wicked-pdf

我正在使用带有rails 3.2.11和ruby 1.9.3的wicked_pdf来从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上加载字体?

3 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:3)

我遇到了这个问题并遵循了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']

答案 2 :(得分:1)

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

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

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

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

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

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

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