Using PDFKit on Heroku

Recently, I've been working on a small project that crawls the web to gather information about trademarks (e.g. number of Google results, placement of sponsored links, etc.).  In the requirements, we needed to have PDF versions of the webpages that were crawled, so I found this to be a great opportunity to try PDFKit and try hosting the project on Heroku.  Initially I got everything working locally, but once I tried running the app on Heroku it didn't have access to the wkhtmltopdf library.  I've outlined my steps to get the PDFKit gem working on Heroku.

1. Setup PDFKit to work locally (gem install pdfkit, added the config.gem lines to your environment.rb or if you're on Rails 3 use the Gemfile)
2. Make sure Heroku installs the PDFKit gem to your slug by either creating a .gems file (Gem Manifest) then have a line inside that file that says pdfkit or if you've setup Bundler on the Heroku Bamboo stack (Heroku Bundler) than just have pdfkit in your Gemfile
3. Download the wkhtmltopdf-0.9.9 Linux Static Binary (amd64) executable (via Google Code), unarchive it, and then place it inside the bin folder of your Rails project.
4. Create an initializer, so in production Heroku will use this to generate the PDF's.  I put this inside of config/initializers/pdfkit.rb



# config/initializers/pdfkit.rb


PDFKit.configure do |config|     


     config.wkhtmltopdf = Rails.root.join('bin', 'wkhtmltopdf-amd64').to_s if Rails.env.production?


end


5. Commit all your changes and add the new files via: git add .
Push your app to Heroku.  PDFKit should work just fine!

 

Some additional tricks from the comments that might be helpful in your app:
If your Heroku app hangs when trying to load images when generating your PDF, check out Julian's post on how to fix this. 

If you'd like to send custom PDF files back to the user (e.g. from HTML stored in your database or a file within your app). This method is much cleaner than rendering the pdf as a file to the /tmp folder, then using send_file.



# Could be one of your controller actions


def show


     html = "<p> Hello world </p>"


     pdfkit_instance = PDFKit.new(html)


     send_data(pdfkit_instance.to_pdf)


end


 

If you would like to email the PDF instead, Andrew Gertig had a great recommendation of using the render_to_string() to take the rendered show page and send it as a PDF.

 



# /controllers/posts_controller.rb


def mail_post


      @post = Post.find(params[:id])


      email = render_to_string(:action => 'show', :layout => false)


      email = PDFKit.new(email)


      email.stylesheets << "#{Rails.root}/public/stylesheets/emailpdf.css"


      email = email.to_pdf


      CustomMailer.email_a_pdf(@post, email).deliver


      redirect_to :action => 'index'


end