cfdocument will take your combination of CFML and HTML and convert it to a PDF. At its simplest, you can stick some text between the opening and closing tags of cfdocument (there is currently no built-in cfdocument script equivalent) and it will render a PDF to the screen. Here is some sample code:
<cfdocument format="PDF"> <cfoutput> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# </cfoutput> </cfdocument>
It would be optimal if anything you produce in a browser will look exactly the same in the cfdocument generated PDF. However, cfdocument currently only supports HTML 4.01, XML 1.0, DOM Level 1 and 2, and CSS1 and CSS2. To be fair, the current support level will cover 90% of most HTML generation you attempt to do. There are 76 supported CSS styles; see http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c21.html for the entire list. Also note that if you have a Word file that you save HTML, the resulting PDF will not look anything like the Word document.
cfdocument has attributes that allow you to set margins, page size, page orientation, and passwords.
<!--- These attributes will create a password protected legal sized PDF with the following characteristics Bottom Margin: 2.0 inches Top Margin: 1 inch Left Margin: 1/2 inch Right Margin: 1 1/2 inch User Password: secret123 Encrypted: 128-bit encryption ---> <cfdocument format="PDF" pagetype="legal" marginbottom="2.0" margintop="1.0" marginleft="0.5" marginright="1.5" userpassword="secret123" encryption="128-bit"> <cfoutput> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# </cfoutput> </cfdocument>
cfdocumentitem can be used to create PDF headers, footers, and page breaks. If you are not using cfdocumentsection (covered next), then where you place the cfdocumentitem in your HTML will make a difference as to how it affects the entire document.
<cfdocument format="PDF"> <cfoutput> <cfdocumentitem type="header"> <h1 style="text-align:center;">BIG FANCY HEADER</h1> </cfdocumentitem> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# <cfdocumentitem type="pagebreak"/> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# <cfdocumentitem type="footer"> <h1 style="text-align:center;">Page #cfdocument.currentPageNumber# of #cfdocument.totalPageCount#</h1> </cfdocumentitem> </cfoutput> </cfdocument>
Sometimes you may want to create a PDF that does not have the same header and footer for every single page (like a title page), or you may have few pages that need different margins. To deal with this, you can use cfdocumentsection, which puts your HTML content into separate blocks, each of which can have their own settings for margins, headers, and footers defined in a cfdocumentitem nested in that cfdocumentsection.
<cfdocument format="PDF"> <cfoutput> <!--- Section 1 ---> <cfdocumentsection name="bookmark1"> <cfdocumentitem type="header"> <h1 style="text-align:center;">BIG FANCY HEADER</h1> </cfdocumentitem> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# <cfdocumentitem type="footer"> <h1 style="text-align:center;">Page #cfdocument.currentPageNumber# of #cfdocument.totalPageCount#</h1> </cfdocumentitem> </cfdocumentsection><!--- Section 2 ---> <cfdocumentsection name="bookmark2"> <cfdocumentitem type="header"> <h1 style="text-align:center;">2nd page header</h1> </cfdocumentitem> Bacon ipsum dolor sit amet sirloin fatback #dateformat(now(), "short")# <cfdocumentitem type="footer"> <h1 style="text-align:center;">Page #cfdocument.currentPageNumber# of #cfdocument.totalPageCount#</h1> </cfdocumentitem> </cfdocumentsection> </cfoutput>
</cfdocument>
If you find that your application must use a lot of cfdocument, here are some tips for improving performance and rendering.
Avoid using relative file paths:
<!--- Don't use these below ---> <link rel="stylesheet" type="text/css" src="../assets/mainStyle.css"> <img src="../images/mypic.png"><!--- INSTEAD use expand path to provide the full path to the file ---> <link rel="stylesheet" type="text/css" src="#expandPath('../assets/')#mainStyle.css"> <img src="#expandPath('../images/')#mypic.png">
Set the localURL attribute to yes. When you set this attribute of cfdocument to true, it tells ColdFusion to retrieve image files directly from the server rather by attempting to use HTTP.
Please consider adding a "Alternative PDF Generator" section. I've been communicating with other developers that are using third-party Java, C and command line solutions because of rendering issues with CFDocument. It appears that the version of IceBrowser/iText that is used is from 2008. (New licensing fees are probably cost preventing Adobe from upgrading.)
https://twitter.com/gamesover/status/752530433481568256
Instead of spending hours attempting to tweak HTML to get it to look close to what I want, I started experimenting with WKHTMLTOPDF, an open source (LGPLv3) command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine. I've found that it's able to quickly produce high quality PDFs with consistent results using ColdFusion 8, 9, 10, 11 & 2016. (I can even generate PDFs offline without using any CFThreads... no Enterprise license required.) It supports all markup that is renderable by WebKit. This means better support for CSS3 (ie, rounded corners) and support for javascript delay, SVG (high quality logos) & webfonts (FontAwesome icons)! You can add headers & footers that are evaluated on-the-fly. I have some related blog posts here:
https://gamesover2600.tumblr.com/search/wkhtmltopdf
What other CF alternatives are being used by other ColdFusion developers... and what CFDocument problems did it solve?