Question

I'm have a problem rendering PDFs using Wicked_PDF. I'm hosting all of my asset-pipeline resources using Amazon S3 and CloudFront, and things are generated fine while in development; however in production the HTML and CSS assets are not being rendered in the generated PDF.

I'm running Rails 3.2.11, Ruby 1.9.3p327, on MAC OSX 10.8.2, wkhtmltopdf 0.9.9, and the current versions of Wicked_PDF and wkhtmltopdf-heroku.

Here is all the relevant information:

Heroku Logs:

2013-04-21T14:13:19.482011+00:00 app[web.1]: Completed 302 Found in 212ms (ActiveRecord: 205.6ms)
2013-04-21T14:13:19.584108+00:00 app[web.1]: Started GET "/office/download/7" for ip_address at 2013-04-21 14:13:19 +0000
2013-04-21T14:13:21.551581+00:00 app[web.1]: Processing by OfficesController#show_pdf as HTML
2013-04-21T14:13:21.551581+00:00 app[web.1]: ***************WICKED***************
2013-04-21T14:13:21.551581+00:00 app[web.1]:   Parameters: {"office_id"=>"7"}
2013-04-21T14:13:21.551581+00:00 app[web.1]:   Rendered appointments/forms/_office.pdf.html.erb within layouts/pdf.html (13.6ms)
2013-04-21T14:13:21.551581+00:00 app[web.1]:   Rendered text template (0.0ms)
2013-04-21T14:13:21.551581+00:00 app[web.1]: Sent data Office.pdf (42.2ms)
2013-04-21T14:13:21.551581+00:00 app[web.1]: Completed 200 OK in 1961ms (Views: 41.9ms | ActiveRecord: 7.8ms)
2013-04-21T14:13:21.554211+00:00 heroku[router]: at=info method=GET path=/office/download/7         
host=www.foobar.com fwd="ip_address" dyno=web.1 connect=1ms service=1971ms status=200 bytes=22019

Routes:

# => Route that generates the PDF

get "/office/download/:office_id" => 'offices#show_pdf'

Controller:

# => app/controllers/offices_controller.rb

def show_pdf
  @office = Office.find_by_id(params[:office_id])
  abrv = @office.abrv
  partial = "appointments/forms/_#{abrv}"
  @format = "pdf"

  respond_to do |format|
    format.pdf do
      render :pdf => "#{@office.name}",
             :template => "#{partial}.pdf.html.erb",
             :layout => "pdf.html",
             :page_size => "A4",
             :encoding => "UTF-8",
             :show_as_html => params[:debug].present?
     end
  end

end

View:

# => app/views/offices/index

<div>
  # List of all offices
</div>

# PDF partials for each office

<%= render 'appointments/forms/office.pdf.html.erb' %>
<%= render 'appointments/forms/office_1.pdf.html.erb' %>
...

PDF Template:

# => app/views/appointments/forms/_office.pdf.html.erb:

<% if @format != 'pdf' %>
  <%= stylesheet_link_tag 'office' # => .css.scss.erb %>
<% else %>
  <%= wicked_pdf_stylesheet_link_tag 'office' # => .css.scss.erb %>
<% end %>

<div class="pdf_styling">
  <p>Bar</p>
</div>

CSS:

# => app/assets/stylesheets/office.css.scss.erb

.pdf_styling {
  background-image: url('https://s3.amazonaws.com/foo/assets/pdf_background_image.jpg');
  width: 100%;
  height: 100%;

  p {
    position: absolute;
    left: 100px;
    right: 100px;
  }
}

Wicked_PDF Initializer:

# => config/initializers/wicked_pdf.rb

WICKED_PDF = {
  :wkhtmltopdf => (Rails.env.test? || Rails.env.development? ? '/usr/local/bin/wkhtmltopdf' : Rails.root.join('bin', 'wkhtmltopdf-amd64').to_s),
  :exe_path => (Rails.env.test? || Rails.env.development? ? '/usr/local/bin/ ' : Rails.root.join('vendor','bin', 'wkhtmltopdf-amd64').to_s)
}

Gemfile:

# PDF Gem
gem 'wicked_pdf'

# PDF to HTML utility
gem 'wkhtmltopdf-binary'

# PDF on heroku
group :production do
  gem "wkhtmltopdf-heroku", :git => 'git://github.com/camdez/wkhtmltopdf-heroku.git'
  gem 'thin'
end

# Asset Pipeline Optimization
gem "asset_sync"   

Again, everything works fine in development, but I just get a blank PDF page in production. There are no errors being raised from within the logs. Is this potentially an issue with having too-few dynos?

I am admittedly a n00b with all this; forgive me. Thanks.

Was it helpful?

Solution

I had the same problems when deploying to production in Heroku.

Two possible areas to address... First off, EVERY Javascript or CSS resource file must be specified as an absolute URL, not just the one that you are specifying in the template code. If you have any JS/CSS files referenced elsewhere, these would also have to be specified in absolute form. Because of this, you'll need to look at your pdf layout file as well

Secondly (and this is what did the trick for me on Heroku), I wound up having to specify each of my resources in config/application.rb like so:

config.assets.precompile += ['blueprint/screen.css', 'jquery.timepicker.css', 'pdf.css', 'jquery.ui.datepicker.js', 'pdf.js', 'jquery.autosize.js', 'jquery.timepicker.js']

I'm not sure why this second step was required but without it, nothing working on Heroku: I got the same blank PDF with no errors that you are reporting, even thought everything worked in development. My experience has been that wkhtmltopdf silently fails if there are resource issues. I blogged about the problem here and also pushed an update to the WickedPDF README documentation which might be helpful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top