Earlier this morning a reader asked about how to send a user a PDF that opened at a particular page. Apparently it is possible to link to a PDF and pass a URL parameter for the page you want to open to, but in his case, he was serving up the PDF via cfcontent. I thought it might be possible to do via DDX, and after searching, I found that this use case is actually documented in the ColdFusion docs, but unfortunately, the XML isn't complete and I had to struggle a bit to get it work. Here's how our docs show it:
<?xml version="1.0" encoding="UTF-8"?>
<DDX xmlns="http://ns.adobe.com/DDX/1.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ns.adobe.com/DDX/1.0/ coldfusion_ddx.xsd">
<PDF result="Out1" initialView="firstView">
...
<InitialViewProfile name="firstView" show="BookmarksPanel" magnification="FitPage"
openToPage="2"/>
...
</DDX>
Not only is that DDX not complete, it isn't right either. Here's the proper DDX:
<?xml version="1.0" encoding="UTF-8"?>
<DDX xmlns="http://ns.adobe.com/DDX/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.adobe.com/DDX/1.0/ coldfusion_ddx.xsd">
<InitialViewProfile name="firstView" openToPage="2"/>
<PDF result="Out1" initialView="firstView">
<PDF source="In1" />
</PDF>
</DDX>
Note that the InitialViewProfile tag is outside of the PDF tag block. Also note we have to specify an input field. So let's put it together in a full example:
<cfsavecontent variable="ddxString">
<?xml version="1.0" encoding="UTF-8"?>
<DDX xmlns="http://ns.adobe.com/DDX/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.adobe.com/DDX/1.0/ coldfusion_ddx.xsd">
<InitialViewProfile name="firstView" openToPage="2"/>
<PDF result="Out1" initialView="firstView">
<PDF source="In1" />
</PDF>
</DDX>
</cfsavecontent> <cfset input = {"In1"=pdfFile}>
<cfset output = {"Out1" = "c:\temp.pdf"}>
<cfpdf ddxfile="#ddxString#" action="processddx" name="result"
inputfiles="#input#" outputfiles="#output#">
<cfdump var="#result#">
<cfset pdfFile = "C:\Users\Raymond\Documents\My Dropbox\Misc Docs\rc120-010d-solr.pdf">
If you've never seen CFPDF/DDX before, then this may be seem a bit weird, but basically, ColdFusion passes the XML as instructions to an embedded Livecycle Doohicky within ColdFusion. These instructions expect inputs and outputs (exactly what depends on the DDX being run), so we pass in an input struct and output struct. I've got hard coded values here but normally it would be dynamic.
And that's it. As I told the person in the other thread, DDX operations are binary and going to be slower than normal. You may want to consider caching this PDF so you can use it next time instead of generating it every time. (In general, any time you do file operations you probably want to store and cache the result. Disk space is cheap. S3 even cheaper.)
Archived Comments
Thanks Ray, this example works like a charm. I was wondering if its possible to use the same technique to open a pdf to a specific 'Destination' within the PDF. I've looked at the documentation, and don't see how to do this using the openToPage value. The CoverPage attribute looks like it maybe a way to open to a destination. Any ideas?
Actually it looks like the destination can be accessed by simpy adding #destinationName to the end of the URL. This works even when the document is returned using cfcontent.
Glad you figured it out. My job here is done. ;)
Trying this out, but the DDXis not valid because the schema, coldfusion_ddx.xsd, can't be located. Am I missing something?
You get that error? Where? While the xsd does not exist, I'm able to run the code just fine.
Thanks for the response. I am a newbie so I assumed I must have missed some important detail. I created the DDX file in Visual Studio assuming since it is an xml file the editor would work out. After posting here, I re-created it in notepad and now it is working fine -- go figure!
Hi Ray,
Thanks for this post.
I managed to set magnification level using your sample code.
I only had a problem with the ddx which was not valid unless i wrote it all in a single line into the cfsavecontent tag.
It also doesn't work when you open the pdf in Chrome but that's a problem with Chrome, not with cf, i guess.
How does it fail in Chrome? I generate PDFs w/ Chrome via CF all the time. (Ok, not all the time, but I have in the past.)
Ok sorry it seems it was some cache issue, it opens now correctly to the specified magnification percentage.
Thanks again
Great post!
When I open the file created, you can open "print dialog" on pdf merged immediately? If possible, how do I change the DDX?
I found the solution:
<PDF result="output1">
<PDF source="doc1"/>
<PDF source="doc2"/>
<JavaScript source="js1" name="openPrintDialog"/>
</PDF>
"js1" is a file .js with this code:
this.print({
bUI: true
});
I was trying to use this to override the size that the pdf is opened up as. I am creating a dynamic report that is in PDF format and I was wondering if I have to save this as a pdf and read from that or if I can pass the cfdocument pdf variable to the input structure. I'm getting errors trying to do so and don't know if is my code or the functionality.
It's been a while for me, but I'm pretty darn sure you have to save it to the file system first.
Hi Ray, follow your blogs constantly.
I'm having an error follow up on this line.
<cfset input = {"In1" = pdfFile}>
Invalid CFML construct found on line 13 at column 16.
ColdFusion was looking at the following text:
{
The CFML compiler was processing:
A cfset tag beginning on line 13, column 2.
Running cf8.0.
I don't remember when implicit struct notation came in, but it must have been CF9, not 8. So translate it so:
<cfset input = structNew()>
<cfset input["In1"] = pdfile>
Sorry for lateness.
Paul's comment from 5-17-12 blew open automatic printing in ColdFusion for me. Something that threw me though: the "source" attribute in the JavaScript tag needs to be in the input structure you send to <cfpdf> via the "inputfiles" attribute. The struct key corresponds to the value you use for "source". Its value is the full path of the file. According to the Adobe docs, you can even use a URL.
Hope that helps someone.
Hi,
It seems like your above code might help me in splitting my pdf into multiple pdf files. i dont know what DDX and coldfusion is. can anybody tell me where i can start from, i mean i need assistance from scratch. i dont know if any third party software is required, so please help me out.
thanks.
You don't need DDX. CFPDF allows you to extract pages from a PDF. You could use that to 'split' a PDF doc.
Actually i want split pdf through javascript so if you can help me in this, it will be very appreciable.
Check out pdfjs then: http://mozilla.github.io/pd...
Thanx Raymond, for the link. I will have a look into that code.