A wrapper for both wkhtmltopdf and chrome-headless plus PDFTK (adds in encryption) for use in Elixir projects.
{:ok, pdf} = PdfGenerator.generate_binary("<html><body><h1>Yay!</h1></body></html>")
- 0.5.4
- BUGFIX introduced in 0.5.0 that would crash
PdfGenerator.PathAgent
when chrome isn't found on path in certain situation. Thanks to @radditude for submitting a patch.
- BUGFIX introduced in 0.5.0 that would crash
For a proper changelog, see CHANGES
It's either
-
wkhtmltopdf or
-
nodejs and possibly chrome/chromium
This will allow you to make more use of Javascript and advanced CSS as it's just your Chrome/Chromium browser rendering your web page as HTML and printing it as PDF. Rendering tend to be a bit faster than with wkhtmltopdf. The price tag is that PDFs printed with chrome/chromium are usually considerably bigger than those generated with wkhtmltopdf.
-
Run
npm -g install chrome-headless-render-pdf puppeteer
.This requires nodejs, of course. This will install a recent chromium and chromedriver to run Chrome in headless mode and use this browser and its API to print PDFs globally on your machine.
If you prefer a project-local install, just use
npm install
This will install dependencies under./node_modules
. Be aware that those won't be packaged in your distribution (I will add support for this later).On some machines, this doesn't install Chromium and fails. Here's how to get this running on Ubuntu 18:
DEBIAN_FRONTEND=noninteractive PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=TRUE \ apt-get install -y chromium-chromedriver \ && npm -g install chrome-headless-render-pdf puppeteer
-
Download wkhtmltopdf and place it in your $PATH. Current binaries can be found here: http://wkhtmltopdf.org/downloads.html
For the impatient (Ubuntu18):
apt-get -y install xfonts-base xfonts-75dpi \ && wget https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox_0.12.5-1.bionic_amd64.deb \ && dpkg -i wkhtmltox_0.12.5-1.bionic_amd64.deb
-
optional: Install
xvfb
(shouldn't be required with the binary mentioned above):To use other wkhtmltopdf executables comiled with an unpatched Qt on systems without an X window server installed, please install
xvfb-run
from your repository (on Debian/Ubuntu:sudo apt-get install xvfb
).I haven't heard any feedback of people using this feature since a while since the wkhtmltopdf projects ships ready-made binaries. I will deprecate this starting in
0.6.0
since, well, YAGNI. -
optional: Install
pdftk
via your package manager or homebrew. The project page also contains a Windows installer. On Debian/Ubuntu just type:apt-get -y install pdftk
Add this to your dependencies in your mix.exs:
def application do
[applications: [
:logger,
:pdf_generator # <-- add this
]]
end
defp deps do
[
# ... whatever else
{ :pdf_generator, ">=0.5.4" }, # <-- and this
]
end
Then pass some html to PdfGenerator.generate
$ iex -S mix
html = "<html><body><p>Hi there!</p></body></html>"
# be aware, this may take a while...
{:ok, filename} = PdfGenerator.generate(html, page_size: "A5")
{:ok, pdf_content} = File.read(filename)
# or, if you prefer methods that raise on error:
filename = PdfGenerator.generate!(html, generator: :chrome)
Or, pass some URL
PdfGenerator.generate {:url, "http://google.com"}, page_size: "A5"
Or, use chrome-headless
html_works_too = "<html><body><h1>Minimalism!"
{:ok, filename} = PdfGenerator.generate html_works_too, generator: :chrome
Or use the bang-methods:
filename = PdfGenerator.generate! "<html>..."
pdf_binary = PdfGenerator.generate_binary! "<html>..."
This module will automatically try to finde both wkhtmltopdf
and pdftk
in
your path. But you may override or explicitly set their paths in your
config/config.exs
.
config :pdf_generator,
wkhtml_path: "/usr/bin/wkhtmltopdf", # <-- this program actually does the heavy lifting
pdftk_path: "/usr/bin/pdftk" # <-- only needed for PDF encryption
or, if you prefer shrome-headless
config :pdf_generator,
use_chrome: true, # <-- make sure you installed node/puppetteer
raise_on_missing_wkhtmltopdf_binary: false # <-- so the app won't complain about a missing wkhtmltopdf
-
filename
- filename for the output pdf file (without .pdf extension, defaults to a random string) -
page_size
:- defaults to
A4
, seewkhtmltopdf
for more options - A4 will be translated to
page-height 11
andpage-width 8.5
when chrome-headless is used
- defaults to
-
open_password
: requirespdftk
, set password to encrypt PDFs with -
edit_password
: requirespdftk
, set password for edit permissions on PDF -
shell_params
: pass custom parameters towkhtmltopdf
. CAUTION: BEWARE OF SHELL INJECTIONS! -
command_prefix
: prefixwkhtmltopdf
with some command or a command with options (e.g.xvfb-run -a
,sudo
..) -
delete_temporary
: immediately remove temp files after generation
You're more than welcome ot submit patches. Please run mix test
to ensure at bit of stability. Tests require a full-fledged environment, with all of wkhtmltopdf
, xvfb
and chrome-headless-render-pdf
available path. Also make to to have run npm install
in the app's base directory (will install chrome-headless-render-pdf non-globally in there). With all these installed, mix test
should run smoothly.
Hint: Getting :enoent
errors ususally means that chrome or xvfb couldn't be run. Yes, this should output a nicer error.
If you want to use this project on heroku, you can use buildpacks instead of binaries
to load pdftk
and wkhtmltopdf
:
https://github.com/fxtentacle/heroku-pdftk-buildpack
https://github.com/dscout/wkhtmltopdf-buildpack
https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/phoenix-static-buildpack
note: The list also includes Elixir and Phoenix buildpacks to show you that they
must be placed after pdftk
and wkhtmltopdf
. It won't work if you load the
Elixir and Phoenix buildpacks first.
This section only applies to wkhtmltopdf
users using wkhtmltopdf w/o the qt patch. If you are using the latest 0.12 binaries from https://downloads.wkhtmltopdf.org (recommended) you can safely skip this section.
If you want to run wkhtmltopdf
with an unpatched verison of webkit that requires
an X Window server, but your server (or Mac) does not have one installed,
you may find the command_prefix
handy:
PdfGenerator.generate "<html..", command_prefix: "xvfb-run"
This can also be configured globally in your config/config.exs
:
config :pdf_generator,
command_prefix: "/usr/bin/xvfb-run"
If you will be generating multiple PDFs simultaneously, or in rapid succession,
you will need to configure xvfb-run
to search for a free X server number,
or set the server number explicitly. You can use the command_prefix
to pass
options to the xvfb-run
command.
config :pdf_generator,
command_prefix: ["xvfb-run", "-a"]
For more info, read the docs on hex or issue
h PdfGenerator
in your iex shell.