Binary Vision blog

Dynamic PDF Generation - Part 3

Welcome back to part three of my series of posts about using ColdFusion to create dynamic PDF documents. In this post I will cover merging, optimising, protecting and linearizing of PDF documents, all using Coldfusion's CFPDF tag.

Merging two PDFs into one document.

This action returns a single PDF from either a directory containing multiple PDF documents, or a comma separated list of PDF documents (either file or CF PDF variable) and can be really useful when creating multiple-sectioned documents, just create a section at a time and then merge into one document at the end -I used this exact technique to allow different custom header and footer content for each section, by applying different watermarks to each section before merging.

First, a comma separated list of documents, here the two source documents are merged into a CF variable called 'myMergedPDF', for further manipulation.

view plain print about
<cfpdf 
    action = "merge"  
    source = "myTest.pdf,myTest2.pdf" 
    name = "myMergedPDf">
 

And now, merging the entire contents of a folder, which by default lists the documents in reverse alphabetical order. The sort order can be controlled further by using the 'order' and 'ascending' attribute. The resutlant PDF is saved to the file system.

view plain print about
<cfpdf 
    action = "merge"  
    source = "c:\pdfstore\pdfstobemerged\" 
    destination = "c:\pdfstore\mergedpdfs\myMergedPdf.pdf">
 

For more advanced PDF merging, you can specify the pages within a PDF document you wish to use in the merge operation. This can be really useful for pulling just a small section from one document and merging it with another, or for inserting a section into an existing PDF, which is what our next snippet does. Using the CFPDFPARAM tag we are able to specify which pages from which document we are merging, giving us very good control over the final PDF content.

view plain print about
<cfpdf action="merge" destination="myMergedPDF.pdf" overwrite="yes"> 
    <cfpdfparam source="myTest.pdf" pages="1-3"> 
    <cfpdfparam source="myTest2.pdf"> 
    <cfpdfparam source="myTest.pdf" pages="4-10"> 
</cfpdf>

That's about it for merging documents, no great hurdles to over come here, for a change, CF does exactly what it says on the tin! :-)

Optimising your PDFs

Coldfusion gives us a method of post-production optimization of PDF documents; this can help us to reduce the size of documents by removing items that are not used within a document, and resampling the images contained within the document. It can greatly affect the size of a document where uncompressed images have been used, rather than finely tuned JPGs or PNGs. Basic usage is simple enough, here we optimise the document using the bicubic algorithm, other options are 'bilinear' and 'nearest_neighbor', but in testing I have found very little difference between the three from an output POV. If you were optimising a very complicated or image intensive document you may see a performance penalty using 'bicubic' or bilinear', where 'nearest_neighbor' would be the fastest of the three.

view plain print about
<cfpdf 
    action = "optimize" 
    source = "myTest.pdf"  
    algo = "bicubic" 
    destination = "myTest.pdf"
    overwrite = "true">


To remove unwanted items from PDFs, there are quite a number of pretty self-explanatory parameters available for the optimize action. These are particularly useful for optimising PDFs created using Acrobat, where file size was previously not an issue, for example on an intranet, and we now want to make available to a wider audience and post them on the internet. Here's the full list of options available to the optimize action:

view plain print about
<cfpdf 
    action = "optimize" 
    source = "myTest.pdf"  
    algo = "bicubic" 
    destination = "myTest.pdf"
    overwrite = "true"
    noattachments = "true" 
    nobookmarks = "true" 
    nocomments = "true" 
    nofonts = "true" 
    nojavascripts = "true" 
    nolinks = "true" 
    nometadata = "true" 
    nothumbnails = "true">

Linearizing your PDFs

Whilst we are talking about displaying PDFs on the web, it is probably a good time to talk about linearizing PDF documents. First, what's a 'linearized' PDF ? Well, a linearized PDF is a PDF designed for faster display on the web, not through file size, but by allowing the first page of the document to display whilst the rest of the document is still downloading in the background. A non-linear PDF will require the user to wait for the entire PDF to arrive their machine before they can view even the first word. As I was designing a system that could generate some very large PDFs (>30MB, and 500 pages) it was important to make sure this was used. To create a linear PDF, use the 'saveOption="linear"' parameter when you save the PDF to disc:

view plain print about
<cfpdf action="write" 
       source="myTest" 
       destination="myTest.pdf" 
       saveOption="linear" 
       overwrite="yes">

Protecting your PDFs

There are two common ways documents are secured, first through password protection, and second through encryption, Coldfusion is very generous in allowing us to do both at the same time, all in one tag!

view plain print about
<cfpdf 
    action = "protect" 
    source = "myTest.pdf"  
    newUserPassword = "password" 
    destination = "myTest.pdf" 
    encrypt = "AES_128" 
    overwrite = "yes" 
    password = "source file password">
 

This code adds a new password to the document (the user is prompted on open), and encrypts the document with AES 128bit encryption. This is compatible with Adobe Reader v7 onwards, if you need further backward compatibility then you will need to downgrade the encryption to one of the other options (see the CFPDF documentation for more information).

And lastly for today, when creating a PDF document you can restrict what actions a user may take once they have it open. To do this you must also set an 'owner' password, which as it's name suggests means if you enter his password on opening, you have access to all the features, whereas a user that enters the normal user password will still be subject to any restrictions placed on the document. In this next example I restrict the regular users to just printing and screen reader access.

view plain print about
<cfpdf 
    action = "protect" 
    source = "myTest.pdf"  
    newUserPassword = "password" 
    destination = "myTest.pdf" 
    encrypt = "AES_128"
    newOwnerPassword="notsoeasypassword" 
    permissions="AllowPrinting,AllowScreenReaders"
    overwrite = "yes" 
    password = "source file password">
 

That's it for this post, I shall return shortly with a final post on PDFs, specifically some CSS/HTML pitfalls I came across, which gave me some headaches but eventually were overcome. Also, a sneaky way to get a user to print the PDF on opening using iText....

Tags: ColdfusionPDF

Back to index