displaying a pdf with coldfusion from outside of the webroot - coldfusion

i don't know if this is possible, but with coldfusion could i display a pdf in the browser thats kept outside of the webroot?
so you can embed a pdf on a page like;
<object data="mypdf.pdf" type="application/pdf">
could i do something like;
<object data="displaymypdf.cfm" type="application/pdf">
where displaymypdf.cfm would return that pdf? kinda like we do for downloads with cfheader/cfcontent?
thanks for any help/pointers

In the CFHEADER tag, use the value: 'inline' and then use CFCONTENT. This should load the pdf into the browser.
<cfheader name="Content-Disposition" value="inline; filename=mypdf.pdf">
<cfcontent file="#yourDirectoryPathHere#mypdf.pdf" type="application/pdf">

Related

Content-disposition being ignored in IE 9 and Firefox 13

I am trying to dynamically create an inline PDF that, when the user chooses to save it, prompts with my custom filename. According to the documentation, the saveasname attribute should do what I want.
(format="PDF" only) The filename that appears in the SaveAs dialog when a user saves a PDF file written to the browser.
However, what is happening in both IE 9 and in Firefox 13.0.1 is that the filename that appears in the SaveAs dialog is the same as my CF template, but with a PDF extension. (In other words, my code is in makepdf.cfm and the SaveAs prompts me to save makepdf.pdf.) In Chrome, however, it works perfectly. (All on Windows 7.)
Here is my code to create the PDF:
<cfdocument format="pdf" bookmark="true" saveasname="MyReport.pdf">
If I explicitly declare the content disposition and content type, like so
<cfheader name="Content-Disposition" value="inline; filename=MyReport.pdf">
<cfcontent type="application/x-pdf">
<cfdocument format="pdf" bookmark="true" saveasname="MyReport.pdf">
Chrome tells me that "Content-Disposition" has been declared twice
Firefox tells me the PDF file is corrupt
IE just ignores it (and still doesn't show the right filename)
If I just rely on the header
<cfheader name="Content-Disposition" value="inline; filename=MyReport.pdf">
<cfcontent type="application/x-pdf">
<cfdocument format="pdf" bookmark="true">
I get the same behavior as the first snippet of code.
I know how to get the browser to prompt for download rather than displaying inline, and everything works as expected then, but that's not the desired behavior.
I need to use times and dates in filenames and the end users are not savvy enough to keep from overwriting their files (should they choose to save them).
Is there something I'm missing that will get IE and Firefox to do what they're supposed to? What other browsers are going to do this? Mobile Safari?
The problem seems to be that "filename=xxx" was really intended for the "attachment" disposition, and not all the browser PDF plugins recognise it as a mechanism for specifying the inline "save as", as you've discovered.
A different approach to getting them all to use your preferred filename would be to manipulate the URL using web server rewrite rules. As a simple example you'd have your script for generating the pdfs and serving them inline: pdf.cfm
<cfheader name="Content-Disposition" value="inline">
<cfdocument format="PDF" mimetype="application/pdf">Test</cfdocument>
Then create a re-write rule which matches URLs in the form /pdf/myfilename and passes them to pdf.cfm. On IIS7 this might be:
<rule name="Inline PDF SaveAs" stopProcessing="true">
<match url="^/pdf/[\w-]+$" ignoreCase="true" />
<action type="Rewrite" url="/pdf.cfm" appendQueryString="false" />
</rule>
This will match filenames containing alphanumeric, underscore and hyphen characters only. You wouldn't want to allow spaces, or invalid filename characters.
When you access /pdf/myreport the PDF will be displayed inline by the plugin, and when you save it, the default filename will be myreport.pdf.
If you're using a framework which supports Search Engine Safe URLs or "routes", you could do the same without needing web server rewrites.
UPDATE: In fact you don't need to use URL rewriting: simply append a forward slash and then the desired filename to the CF script URL, e.g.
/pdf.cfm/myreport
The plugin will use whatever comes after the final slash as the "Save As..." name.
Make sure you use ATTACHMENT and not INLINE.
IE does NOT like INLINE and will open a word document as READ ONLY as well as not assuming the filename you give it.
Example:
<cfheader name="content-disposition" value="attachment; filename=#filename#.doc" charset="utf-8">
NOT
<cfheader name="content-disposition" value="inline; filename=#filename#.doc" charset="utf-8">
I would use the name attribute of the cfdocument tag which will store the contents in a variable. Then use the cfheader and cfcontent tags as you have above with the exception of replacing "inline;" with "attachment;"
I use code like this:
<cfdocument name="pdf"> ... </cfdocument>
<cfheader name="Content-Disposition" value="attachment;filename=MyReport.pdf;" />
<cfcontent type="application/pdf" variable="#pdf#" />

Saving content to a .DOC file using ColdFusion

I'm not having any issues writing the content to the .doc file. The problem I'm having is getting the file to NOT download to the user's browser automatically after creation. I just want to have the .doc file created in the background, then the user can download the file from a web page at anytime. Here's the code I'm working with:
<cfheader name="Content-disposition" value="filename=Quote_#arguments.QuoteNumber#_#arguments.Revision#.doc">
<cfcontent type="application/msword">
<cfoutput>#WordDoc#</cfoutput>
<cffile action="copy" source="#application.AbsPath#\media\quotes\BlankQuote.doc" destination="#application.AbsPath#\media\quotes\Quote_#arguments.QuoteNumber#_#arguments.Revision#.doc" />
<cffile action="write" file="#application.AbsPath#\media\quotes\Quote_#arguments.QuoteNumber#_#arguments.Revision#.doc" output="#WordDoc#" />
You're problem is the <cfheader> tag... that's what is triggering the doc to open.
I would do something like this instead.
<cfsavecontent variable="whatever">
<cfoutput>#WordDoc#</cfoutput>
</cfsavecontent>
<cffile action="write" file="#application.AbsPath#\media\quotes\Quote_#arguments.QuoteNumber#_#arguments.Revision#.doc" output="#whatever#" />

how to save xml in user's computer in coldfusion?

I am invoking a ColdFusion webservice through cfinvoke
<cfinvoke
method="getUsers"
returnvariable="rawXMLUserList"
webservice="http://www.xyz.com/getusers.cfc?wsdl"
>
<cfinvokeargument name="userid" value="123">
</cfinvoke>
And I am storing XML returnvariable into userList variable
<cfset userList = XmlParse(rawXMLUserLis)><br/>
how to save abc.xml on user's computer, using cffile it is saving on server's computer, i have to save it on user's computer who invokes this "getUsers" method.
Thanks
Kishor
When you run XMLParse(), you're turning it into a CF XML Document Object. You need to use ColdFusion's toString(xmlObject) function when outputting it.
<cfheader name="content-disposition" value="attachment;filename=abc.xml">
<cfcontent type="application/xml;charset=utf-8" reset="true">
<cfoutput>#toString(userList)#</cfoutput>
Another way is to write the file to a web directory (cffile action=write) and then cflocation the user to the file.
You need to tell the user's browser to download the file, not display it. Generally with something like this (not tested):
<cfheader name="content-disposition" value="attachment;filename=abc.xml">
<cfcontent type="application/xml;charset=utf-8" reset="true">
<cfoutput>#userList#</cfoutput>
cfheader generates a custom HTTP header.
cfcontent sets the MIME content encoding header for the page.

Empty page displayed with cfcontent in a popup (unless manual refresh)

I have a ColdFusion page calling a cfm page as a popup through window.open(..). The target page is a cfm that loads a PDF file. The called page code is the following:
<cfcontent type="application/pdf" file="/deploy/cfusion.ear/cfusion.war/myPDF.pdf"/>
<cfflush>
<script language="javascript">
window.location.reload();
</script>
Unfortunately, I am getting only a blank page unless I manually refresh the page (going to the popup URL bar and hitting Enter) to have its contents displayed by the browser.
What is strange is that if I replace the caller page code from window.open() to document.url = the PDF is displayed without the need of refreshing the page.
Do you have any suggestions here how to call the target page as a popup and having it load without the need of a manual refresh?
Thanks.
The problem is that you are mixing javascript and PDF content together. It should really just be this:
<cfcontent type="application/pdf" file="/deploy/cfusion.ear/cfusion.war/myPDF.pdf"/>
This will return the full contents of that PDF to the browser.
What were you trying to do with the javascript code?
edit It sounds like it could be something to do with caching. To prevent that, try adding some cache control headers to your file:
<cfheader name="expires" value="#getHttpTimeString(now())#">
<cfheader name="pragma" value="no-cache">
<cfheader name="cache-control" value="no-cache, no-store, must-revalidate">
<cfcontent type="application/pdf" file="/deploy/cfusion.ear/cfusion.war/myPDF.pdf"/>
If that doesn't work, try adding this one too:
<cfheader name="Content-Disposition" value="attachment; filename=myPDF.pdf">
The solution I adopted was that of calling a proxy page and then that proxy page generates the PDF file. So:
window.open('2') // open in a popup the PDF
document.location = '3' // proxy
cfcontent type='application/pdf' file='...' // generate PDF
Why I cannot have 1 and 3 only is for now a mystery but in my case it works perfectly.

How to generate PDF from .cfm page in Mac

I am using <cfdocument> tag of coldfusion 7. Using CFEclipse and working on MacOS.
I have written the following code:
<cfdocument format="pdf">
SitePoint.com - Introduction to ColdFusion 7
PDF Generation
This is an example of PDF generation using ColdFusion 7.
</cfdocument>
But instead of asking me to save this file in .pdf format, its trying to open it in .cfm format.
How can I save it in .pdf format? Thanks!
Unless you tell it otherwise, the webserver returns the results of a CFM call as text. You need to use CFContent with CFHeader to alert the browser that the results it will be recieving are of a different type. Something like:
<cfheader name="Content-Disposition" value="inline; filename=document.pdf">
<cfcontent type="application/x-pdf">
<cfdocument>...</cfdocument>
I may have the MIME type wrong there. I'm doing this from memory. Check the docs for more help.
If you are on CF8 or higher then use the saveAsName attribute:
<cfdocument saveAsName=""
Either that or the method suggested by Ben above should work
You might also need to import the style sheet as well. So you can get the desired formatting. It needs to be imported after cfdocument.
<cfdocument
format="pdf"
filename = "canwriteurfile.pdf"
overwrite = "yes"
marginBottom = ".2"
marginLeft = ".4"
marginRight = ".4"
marginTop = ".2">
<style type="text/css">#import "pdf.css";</style>
BLAHHH BLAHHH PDF FORMATTING STUFF
</cfdocument>
Try:
<cfdocument format="PDF" name="myPDF">
<html>
<body>
SitePoint.com - Introduction to ColdFusion 7
PDF Generation
This is an example of PDF generation using ColdFusion 7.
</body>
</html>
</cfdocument>
<cfpdf action = "write" destination = "pdf_path" source = "myPDF" overwrite = "yes"/>
<cflocation url="pdf_path"/>
Whis this you save the PDF on disk