tags:

views:

988

answers:

5

I would like to turn the HTML generated by my CFM page into a PDF, and have the user prompted with the standard "Save As" prompt when navigating to my page.

A: 

I'm not that familiar with ColdFusion, but what you need to do is set the Content-Type of the page when the user requests it to be application/octet-stream. This will prompt them for a download every time.

Hope this helps!

Frank Wiles, Revolution Systems, www.revsys.com

Frank Wiles
+4  A: 

You should use the cfdocument tag (with format="PDF") to generate the PDF by placing it around the page you are generating. You'll want to specify a filename attribute, otherwise the document will just stream right to your browser.

After you have saved the content as a PDF, use cfheader and cfcontent in combination to output the PDF as an attachment ("Save As") and add the file to the response stream. I also added deletefile="Yes" on the cfcontent tag to keep the file system clean of the files.

<cfdocument format="PDF" filename="file.pdf" overwrite="Yes">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <title>Hello World</title>
</head>
<body>
    Hello World
</body>
</html>
</cfdocument>
<cfheader name="Content-Disposition" value="attachment;filename=file.pdf">
<cfcontent type="application/octet-stream" file="#expandPath('.')#\file.pdf" deletefile="Yes">

As an aside: I'm just using file.pdf for the filename in the example below, but you might want to use some random or session generated string for the filename to avoid problems resulting from race conditions.

Soldarnal
+1  A: 

If you want to avoid storing the PDF at all, using cfdocument without a filename will send the pdf (of flashpaper) directly to the browser without using the cfheader and cfcontent.

Caveat: Like with using cfheader/cfcontent, you need to do this before the cache gets flushed to the browser, since it's basically doing the same thing without having to store the file.

To get the content, I would probably use cfsavecontent wrapped around the same calls/includes/etc. that generate the page, with two major exceptions. cfdocument seems to have issues with external stylesheets, so using an include to put the styles directly into the document is probably a good idea. You can try using an @import instead -- it works for some people. Also, I'd be careful about relative links to images, as they can sometimes break.

Ben Doom
+2  A: 

The <cfdocument> approach is the sanctioned way to get it done, however it does not offer everything possible in the way of manipulating existing PDF documents. I had a project where I needed to generate coupons based using a pre-designed, print-resolution PDF template. <cfdocument> would have let me approximate the output, but only with bitmap images embedded in HTML. True, I could fake print-resolution by making a large image and scaling it in HTML, but the original was a nice, clean, vector-image file and I wanted to use that instead.

I ended up using a copy of <cfx_pdf> to get the job done. (Developer's Site, CF Tag Store) It's a CF wrapper around a Java PDF library that lets you manipulate existing PDF documents, including filling out PDF forms, setting permissions, merging files, drawing vector graphics, tables, and text, use custom fonts, etc, etc. If you are willing to work with it, you can get some pretty spectacular results.

The one drawback is that it appears the developer has left this product out to pasture for a long time. The developer site is still copyright 2003 and doesn't mention anything past ColdFusion MX 6.1. I ended up having to break some of the encrypted templates in order to fix a couple of bugs and make it work as I needed it to. Nontheless, it is a powerful tool.

Andy Waschick