Stamping PDFs with a watermark in eZ Publish
By: Thiago Campos Viana | January 20, 2016 | Business solutions, Case study, eZ Publish development tips, Web solutions, PDF, PDFtk, and watermark
When running an intranet or an otherwise password-protected site, you sometimes need to share confidential or sensitive files, specifically PDFs. It is a challenge to balance the confidential nature of the files while allowing privileged users to download and work with the files normally. One lightweight approach is to stamp a watermark onto each page of the PDF. Instead of just a big "confidential" watermark you can customize each download so that each file is stamped with, for example, the current user's name and the current date.
On an eZ Publish intranet, we implemented PDF watermarking using PDFtk and ImageMagick, which are two open source command line tools. ImageMagick creates a single-page watermark PDF, and then PDFtk finishes the job by stamping this PDF onto each page of the downloaded file.
In order to install PDFtk on Ubuntu, for example, you can run this command:
sudo apt-get install pdftk
Similarly, you can install ImageMagick as follows:
sudo apt-get install imagemagick --fix-missing
Let's first try the features on the command line outside of eZ Publish or the download action.
To create a one-page PDF with a test name and date, run this command:
convert -size 2550x3500 -bordercolor white -border 20x20 -transparent white -pointsize 64 -fill red -font Helvetica-Bold label:'Downloaded by Thiago Campos Viana on 1/19/2016' ./test.pdf
This should create a new file named test.pdf in your current directory, containing the text: "Downloaded by Thiago Campos Viana on 1/19/2016".
Now download a test PDF with a few pages, and save it with the name pdf.pdf in your current directory. Then run this command to stamp pdf.pdf with test.pdf:
pdftk pdf.pdf stamp test.pdf output pdf_stamped.pdf
This will create a another file, pdf_stamped.pdf, with the desired watermark!
We can port this logic to eZ Publish by creating a new module to serve downloaded files. It will act just like the built-in content/download module view, except with the desired watermark.
We have created a sample project, mugo stamppdf, which shows how to port these commands to PHP and the eZ Publish content management system. For illustration purposes, here's a test module view that hard-codes the PDF to convert:
$pdf = 'extension/stamppdf/design/standard/images/MugoCollaborationWorkflowProductSheet.pdf'; $label = $http->postVariable('pdf_string'); $filename = time() . '_' . rand(1,1000) . '.pdf'; $stamp = eZSys::varDirectory() . DIRECTORY_SEPARATOR . 'cache/stamp_' . $filename; exec("convert -size 2550x3500 -bordercolor white -border 20x20 -transparent white -pointsize 64 -fill red -font Helvetica-Bold label:'{$label}' {$stamp}" ); header("Content-Type: application/pdf"); header("Cache-Control: no-cache"); header("Accept-Ranges: none"); header("Content-Disposition: attachment; filename=\"MugoCollaborationWorkflowProductSheet.pdf\""); ob_start(); passthru( "pdftk {$pdf} stamp {$stamp} output -"); $output = ob_get_contents(); ob_end_clean(); unlink($stamp); print($output); eZExecution::cleanExit();
There is also a "download" view that follows this URL pattern: /stamppdf/download/{ObjectID}. It will look for a file attribute and stamp the PDF within that attribute. This way, you can build links that will download files with dynamic, personalized watermarks. You can take this one step further by also adding an attribute ID and support for overriding the file name, just like the built-in "content/download" view. For extra security, you can also create a rewrite rule from "content/download" URLs to "stamppdf/download".