How can I automate HTML-to-PDF conversions?

Viewed 74926

I've been using htmldoc for a while, but I've run into some fairly serious limitations. I need the end solution to work on a Linux box. I'll be calling this library/utility/application from a Perl app, so any Perl interfaces would be a bonus.

16 Answers

NOTE: This answer is from 2008 and is probably now incorrect; please check the other answers

PrinceXML is the best one I've seen (it parses regular HTML as well as XML/XHTML). How is it the best? Well, it passes the acid2 test which I thought was pretty darn impressive

It is however, quite expensive

I did a bit of googling for you and came up with two options. There may be more, my google strategy was to try "webkit command-line pdf" and "gecko command-line pdf", basically looking for commandline programs that embed the two popular open-source rendering engines in command-line renderers. Here's what I found:

Firefox command-line printer - outputs to pdf and png

wkpdf - while this is for mac, it's probably pretty portable.

I wont claim this is the "best" solution but it is "a" solution i have used.

HTML Input --> HTML 2 PS --> PS 2 PDF --> PDF Output

This would be total overkill, but you could download and install mirth. It is a message routing engine, but it has the ability to convert html to pdf, so you could set it up to pick up an html file in a folder, convert to pdf, and drop the pdf in the same or other folder. Like I said, overkill, a bit of a learning curve, but it's free, and java so you can run it on linux if you like. And all your perl app would have to do is drop the html to a file.

I have found Electroshot to be supportive of modern CSS features, particularly layout. This was after struggling with wkhtmltopdf showing its age in not supporting things like CSS3.

From Electroshot's features description:

Electroshot uses Electron, which offers the most recent stable version of Chrome (rather than one from years ago); this means that pages render as they would in a browser...

I've been able to use Bootstrap 4 to design a page, and then use Electroshot to render a PDF very closely resembling the HTML/CSS.

You can install the free Calibre, and use the ebook-convert command line utility it has, to convert many html documents into a single epub, or pdf.

https://manual.calibre-ebook.com/generated/en/ebook-convert.html

Idea comes from here

I haven't used it, but this npm module wraps this process up like my following bash script, but probably better ;-)

For me, on my mac, I use the following bash script to convert a local html website to a PDF:

convert_html_to_pdf.sh

function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF
  
  Converts an html file to pdf, epub, mobi or more if you look!

  usage: input.html output.{pdf|epub|mobi}
  
  e.g. 
  
  $ME index.html output.pdf 

  Note: Requires Calibre be installed. more info here: https://ebooks.stackexchange.com/a/6285
EOF
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ "$1" == "--help" ]
then
  show_help
fi

/Applications/calibre.app/Contents/MacOS/ebook-convert $1 $2 --max-levels=1

An alternative solution that hasn't been answered here is to use an API.

That advantage of them is that you externalize the resources needed for the job and have an up-to-date service that implements the recent features (no needs to update the code or install bugfixes).

For instance, with PDFShift, you can do that with a single POST request at:

POST https://api.pdfshift.io/v2/convert/

And passing the "source" (either an URL or a raw HTML code), and you'll get back a PDF in binary. (Disclaimer: I work at PDFShift).

Here's a code sample in Python:

import requests

response = requests.post(
    'https://api.pdfshift.io/v2/convert/',
    auth=('user_api_key', ''),
    json={"source": "https://en.wikipedia.org/wiki/PDF", "landscape": False, "use_print": False}
)

response.raise_for_status()

with open('wikipedia.pdf', 'wb') as f:
    f.write(response.content)

And your PDF will be located at ./wikipedia.pdf

Here is a nice easy-to-install version of headless Chrome:

https://www.npmjs.com/package/chrome-headless-render-pdf

Unlike "standard" headless chrome, this does not show the annoying auto-generated headers and footers!

Or there is unoconv (which uses LibreOffice behind the scenes) can make pdfs from html:

unoconv -f pdf mypage.html

You can install it on most Linux flavours via the package manager, e.g. apt-get install unoconv

That's nice and easy for simple files. If you need javascript of css support, then use headless Chrome.

I have started to put together a tool to provide a simplified interface to common actions.

You can convert an HTML to a PDF like this:

$ npm install @lancejpollard/act -g
$ act convert tmp/index.html -o tmp/index.pdf -w 2000px -h 3000px

This will create a new PDF for the HTML file.

If nothing else check out the source and see how to write your own script to do this in JavaScript.

wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine. These run entirely "headless" and do not require a display or display service.

How to use it?

  1. Download a precompiled binary or build from source https://wkhtmltopdf.org/downloads.html

    https://github.com/wkhtmltopdf/wkhtmltopdf

  2. Create your HTML document that you want to turn into a PDF (or image)

  3. Run your HTML document through the tool.

Usage: wkhtmltopdf input.html output_name.pdf

I often get very good results when using the ebook-convert command line tool that ships with Calibre.

ebook-convert <input.html> <output.pdf>

Check the numerous options for tweaking in the manual. For example, it is possible to automatically generate a table of contents based on H1/H2/... headlines (or anything using XPath expressions, basically).

Please note: Calibre focuses on digital documents and I don't know how well ebook-convert works for very complicated HTML. Worth a try though. :-)

Related