Blog» Generate highly customized PDFs with wkhtmltopdf and eZ Publish

Generate highly customized PDFs with wkhtmltopdf and eZ Publish


One of our customer websites sells research reports where all of the content is built and managed in the eZ Publish content management system. These reports are served via HTML through a gated website portal. They wanted to add a dynamic PDF report generation feature (based on content in the CMS); the PDF template was highly customized with nice layouts and styles, cover and back pages, custom page breaks, and much more. Over the years we've had good experiences with the ParadoxPDF extension. However due to its lack of HTML5 + CSS3 support and relatively high server load, we decided to look for an alternative solution. We found that wkhtmltopdf does a great job at producing highly styled PDFs, and we were able to integrate it nicely with eZ Publish.

Among the downsides of ParadoxPDF are that it is based on the Java application flying-saucer, which has not been updated since 2011. It only supports CSS2, and doesn't support page breaks using CSS for example. wkhtmltopdf uses qtwebkit, which supports HTML5 and CSS3, and is actively maintained.

Is your website accessible to people with disabilities?

Get our beginner's guide to website accessibility

Download your FREE copy

We also ran some performance tests and found that wkhtmltopdf can generate PDFs up to twice as fast as ParadoxPDF.

Here is some example code on how to use wkhtmltopdf to generate PDFs in eZ Publish. It includes a cover page, a back page, and a table of contents.

// Initialize the PDF using this library: https://github.com/mikehaertl/phpwkhtmltopdf
$pdf = new Pdf();
 
// specify wkhtmltopdf options; see: http://wkhtmltopdf.org/usage/wkhtmltopdf.txt
 
$options = array(
    'page-width'     => '216mm',
    'page-height'     => '279mm',
    'dpi'            => 96,
       'image-quality' => 100,
       //'margin-top'     => '16mm',
       'margin-right'   => '14mm',
    'margin-bottom'  => '25mm',
       'margin-left'    => '14mm',
       'header-spacing' => 15,
       'footer-spacing' => 5,
       'disable-smart-shrinking',
       'no-outline',
       'user-style-sheet' => 'extension/myextension/design/standard/stylesheets/pdf.css',
       'footer-html' => 'extension/myextension/design/standard/templates/pdf/footer.html',
       'header-html' => 'extension/myextension/design/standard/templates/pdf/header.html'
);
 
$pdf->setOptions( $options );
 
// uses eZ Template to build the cover and frontpage
$tpl = eZTemplate::factory();
$tpl->setVariable( 'object', $object );
$pdf->addPage( $tpl->fetch( 'design:pdf/cover.tpl' ) );
$pdf->addPage( $tpl->fetch( 'design:pdf/frontpage.tpl' ) );
 
// Adds a Table of Contents
$pdf->addToc(array('user-style-sheet' => 'extension/myextension/design/standard/stylesheets/pdf.css','xsl-style-sheet' => 'extension/myextension/design/standard/stylesheets/toc.xsl'));
 
// Fill the body of the PDF
$pdf->addPage( $tpl->fetch( 'design:pdf/main_body.tpl' ) );
 
// Adds the backpage
$pdf->addPage( $tpl->fetch( 'design:pdf/backpage.tpl' ) );
 
// Downloads the PDF
$pdf->send( $node->attribute('name') . '_Report.pdf');

header.html

<!doctype html>
<html>
    <head>
            <meta charset="utf-8">
            <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,600,800,400italic,600italic,700italic,800italic,300,300italic' rel='stylesheet' type='text/css'>
    </head>
    <body id="pdf-header">
            <header>
                    <span class="report-name">
                            SOME NAME HERE {pdf_name}
         </span>
                    <span class="report-date">{pdf_date}</span>
            </header>
    </body>
</html>

footer.html

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700,600,800,400italic,600italic,700italic,800italic,300,300italic' rel='stylesheet' type='text/css'>
        <script>
        function pagination()
        {
                var vars = {};
                var x = document.location.search.substring(1).split('&');
 
                for (var i in x)
                {
                        var z = x[i].split('=', 2);
                        vars[z[0]] = unescape(z[1]);
                }
 
                var x = ['frompage','topage','page','webpage','section','subsection','subsubsection'];
 
                for (var i in x)
                {
                        var y = document.getElementsByClassName(x[i]);
 
                        for (var j = 0; j < y.length; ++j)
                        {
                                y[j].textContent = vars[x[i]];
                         }
                }
        }
        </script>
    </head>
 
    <body id="pdf-footer" onload="pagination()">
    <span class="copyright">
                    © Copyright MySite. All rights reserved. 
            </span>
            <span class="page"></span>
    </body>
</html>

To help other eZ Publish developers get started with wkhtmltopdf, we have created a very simple extension, mugo_wkhtmltopdf, to illustrate an initial integration. You can check the file node.php and see that we are using the phpwkhtmltopdf library. That library includes other examples to show how to create more complex PDFs.

To use wkhtmltopdf you also need to install the tool itself! In our sample extension's readme file, we explain how to install it on CentOS. There is also public documentation on how to install wkhtmltopdf on Ubuntu; for Mac and Windows you can run the installer

One alternative solution for generating PDFs from your CMS is to use a third-party service -- you would interact with an API, sending the HTML and receiving the PDF back. This is worth considering if you do not have a requirement (such as a privacy one) to self-host everything.


Related Blog Posts

Subscription-based sites: softer / combination paywall solution

On subscription-based websites, digital publishers often restrict the majority of content to registered users and/or paid subscribers. However, publishers...

Read more »

eZ Publish websites for publishing companies

Over the years we've worked on many websites in the publishing industry. Each has a unique set of requirements and challenges, but we've been able to...

Read more »

Fixed positioning of page elements while scrolling

We recently implemented two different designs where the menu remained fixed to the edge of the screen as the user scrolled. One case involved vertical...

Read more »

Weather widgets and API with Weather Underground

Many weather sites offer embeddable widgets to display weather forecasts on your website. However, if you want to customize the look of the widget, your...

Read more »

Comments

blog comments powered by Disqus

Hi, we're Mugo Web - Nice to meet you!

We're a group of web experts who solve complex web problems.

Learn more about us »

Search


Categories


Yes - we can do that.

We can do that

Many years of experience with complex websites allows us to offer total solutions.

Learn more about what we can do »

We love our clients (and they love us too)

Collage of logos : American express, Habitat, Car and Driver, Rasmussen, and American museum of Natural History

We've solved problems across North America and around the world.

Learn more about what we've done »

We tweet too

Follow us on Twitter for the latest Mugo happenings

mugo twitter page @mugo

© 2008 - 2017 Mugo Web. All rights reserved.