Generating PDFs in Rails with PDFKit and deploying to a server
I’ve been using the rather excellent PDFKit library on a recent Ruby on Rails project to generate PDF reports. The API is perfect: have some HTML, give me a PDF back.
In my controller I simply have:
def download_pdf html = render_to_string(:action => '../pdf/my_template', :layout => false) pdf = PDFKit.new(html) send_data(pdf.to_pdf) end
:action option is a path to a view file. What could be simpler? To get this up and running there were a couple steps. First add a line to the Gemfile
and then install the wkhtmltopdf library using
brew install wkhtmltopdf
And then I tried to deploy to a server…
Very pleased with my new sexy PDF reports I wanted to push my code to the server. I did a quick
sudo apt-get install wkhtmltopdf
to grab the package, loaded up the site and hit the download button: Internal Server Error. Wat!? Looking in the log file:
command failed: "/usr/bin/wkhtmltopdf" "--page-size" "Letter" "--margin-top" "0.75in" "--margin-right" "0.75in" "--margin-bottom" "0.75in" "--margin-left" "0.75in" "--encoding" "UTF-8" "--print-media-type" "--quiet" "-" "-"
Huh? I then tried to run the command from the command line to see if I could get a more useful error message:
$ wkhtmltopdf http://google.com google.pdf wkhtmltopdf: cannot connect to X server
Damn. It turns out that the standard wkhtmltopdf package needs the server to have a window manager running and the chances are your server, like this one, doesn’t have a GUI interface. So what now? Well after a bit of Googling I was starting to get worried, until somebody (I forget where, but thank you!) mentioned that the binaries that can be downloaded from the project’s repo are built against qt and don’t depend on X running! Result!
Looking at the installation instructions page we find this snippet of joy labelled ‘Or….’ under Linux (Ubuntu):
# first, installing dependencies sudo aptitude install openssl build-essential xorg libssl-dev # for 64bits OS wget http://wkhtmltopdf.googlecode.com/files/wkhtmltopdf-0.9.9-static-amd64.tar.bz2 tar xvjf wkhtmltopdf-0.9.9-static-amd64.tar.bz2 mv wkhtmltopdf-amd64 /usr/local/bin/wkhtmltopdf chmod +x /usr/local/bin/wkhtmltopdf
This worked perfectly and all that remained was to tell PDFKit where to find this new binary. I put a pdfkit.rb in my initializers directory with the following in:
PDFKit.configure do |config| config.wkhtmltopdf = '/usr/local/bin/wkhtmltopdf' if Rails.env.production? end
Bingo! PDF downloads are now running on the site.