Thanks to your tips and Ben Nadel's QueryToCSV solution, I'm now able to generate CSV files from my queries. However, I'd like to allow the user to choose where to save the generated file. The documentation states that:
The following tag can force most browsers to display a dialog box that asks users
whether they want to save the contents of the file specified by the cfcontent tag
using the filename specified by the filename value. If the user selects to open
the file, most browsers open the file in the related application, not the browser
window.
<cfheader name="Content-Disposition" value="attachment; filename=filename.ext">
This works for PDF files, but I can't make it work with CSV files. Currently I'm writing the file to a temp file first, then calling cfcontent, then cfheader:
<cffile
action="WRITE"
file="#filename#"
output="#CSVString#"
/>
<cfcontent file="#filename#" type="text/plain" >
<cfheader name="Content-Disposition" value="attachment; filename=#filename#">
This works to write the file to the temp directory, then to the browser window; but I can't figure out how to allow the user to choose where to save.
Try text/csv instead of text/plain for your content type?
Browsers will assume that plain text can/should be displayed on screen, whereas they (should) ask the user what to do for CSV data.
Flip them around:
<cfheader name="Content-Disposition" value="attachment; filename=#filename#">
<cfcontent file="#filename#" type="text/plain">
Also, based on your code above, you wouldn't want to EXACTLY use the #filename# variable in both places, because #filename# is your output destination of your <CFFILE> tag, which implies an absolute full path (ie. C:\temp\mycsvfile.csv), however, that is not what you want in your Content-Disposition header--you want the filename itself...'mycsvfile.csv'. You may want to come up with a 2nd variable for that.
Related
In my Application.cfc, I setup a mapping
this.mappings["/downloads"]="J:\Downloads\documents";
In my template, I have
<cfdirectory action="list" directory="#expandpath("/downloads")#" filter="*.zip|*.docx" name="downloads" recurse="yes">
<!--- <cfdump var="#expandpath("/software")#"> --->
<cfdump var="#downloads#">
<ul>
<cfoutput query="#downloads#">
<li>#downloads.name#</li>
</cfoutput>
</ul>
I'm trying to make the documents downloadable but when the link is clicked, nothing is happening which makes me think my links are not correct however when I mouse over the link, I see the full path which is correct.
What am I missing to make the list of documents clickable?
Here is the URL displayed when mouseover the 3rd document for example.
Since the files are outside of your webroot you will need to have ColdFusion read the file and send it back to the browser.
You will need to create a page, like download.cfm, that can accept a URL parameter to know which file to access. Once you have selected the file you can use something like the following to stream the file.
<cfheader name="Content-disposition" value="attachment;filename=#datafile#">
<cfcontent file="#datafile#" type="application/pdf">
The above code was pulled from https://www.raymondcamden.com/2006/03/10/Ask-a-Jedi-Using-ColdFusion-to-serve-files
WARNING:
Reading URL parameters in this way and giving people access to the filesystem is extremely unsafe. Safer alternatives should be considered before moving something like this into a production environment.
All I needed to do for this exercise is to setup a mapping in my Application.cfc. As others have stated, there is zero security here but for the purpose of this exercise of understanding virtual directories (IIS) and aliases (CommandBox), this is sufficient.
this.mappings["/guides"]="J:\guides";
Then I can use cfdirectory to build my query object
<cfdirectory action="list" directory="j:\guides" recurse="false" name="nameofqry" type="file" sort="datelastmodified desc" filter="*.docx">
Next, perform a cfoutput using my alias as the a href link
<cfoutput query="nameofqry" maxrows="40">
<li>#nameofqry.name#</li>
</cfoutput>
I know coldfusion has some handling for word docs, namely converting them to .pdf. I want to show a document inline without my users having to convert them. Can I programmatically perform the "save as..." int the "wsFormatFilteredHTML" format?
Try this.
If your word content is a variable:
<cfheader name=“Content-disposition” value=“attachment;filename=blah.docx”>
<cfcontent type="application/msword" reset="yes">
#wordconent#
If it's an actual file you should be able to serve directly:
<cfcontent type="application/msword" file="path/filename.docx">
That's from memory so it might take some trial and error. good luck :)
It seems that when I use the <cfsavecontent> tag, the output of that is being served by the server (without the variable being outputted), which, to me, kind of defeats the purpose of <cfsavecontent>.
If this is important: my application uses ColdSpring, ModelGlue and Transfer ORM.
Here's my example code in a function:
<cfsavecontent variable="testvar">
<cfinclude template="test.cfm" />
</cfsavecontent>
<cfreturn testvar>
And the template:
<cfdocument format="PDF" pagetype="A4" orientation="portrait" unit="cm">
<cfoutput>
<!--- PDF content here --->
</cfoutput>
</cfdocument>
The PDF content is being parsed by my browser (Google Chrome), while the view hasn't even been loaded in. How can I best prevent this from happening?
Just to clarify: I am not outputting the #testvar# variable yet in this code, though it seems it loads the template in the browser anyways.
To achieve what you're trying to do, should you not simply be using the name attribute of <cfdocument> to put the PDF data into a variable, instead of trying to <cfsavecontent> it?
Disclosure: I've never used <cfdocument> for anything other than proof-of-concept code and testing, but that's what I'm inferring from the docs.
As I also needed to make multiple PDF documents merge, I ended up doing the following. Many thanks to Adam Cameron for providing the solution to my initial issue.
In the template file, I use the <cfdocument> tag with the name attribute to save the PDF in a variable (thanks to Adam Cameron for this)
Then, I store all the PDF documents in an array in their binary format
In my view, I merge the PDF documents together by using <cfpdf>'s merge action, and using a cfloop, to loop over the array, inside it.
Finally, I display the content by using <cfcontent> and using the variable attribute with toBinary(myPdf)
This got me to where I am.
cfinclude will process the test.cfm page, and the way you configured cfdocument will cause "opening" of pdf document in your browser.
You can prevent openning of this file by saving file on the disc:
<cfdocument format="PDF" pagetype="A4" orientation="portrait" unit="cm" filename ="test.pdf" overwrite ="yes">
But this will not prevent execution of cfinclude in the cfcontent tag, it will just prevent opening in the browser.
You can observe cfinclude as request to the server, it will always be executed.
The solution would be to invoke request on test.cfm file which contains cfdocument in the moment that you actually want to generate pdf.
Example: Use javascript on client to invoke report service which will generate and pop out the screen with pdf report.
Hope this helps.
I am using <cfpdfform> to populate a LiveCycle Designer developed pdf form. I've excluded the destination attribute and the pdf shows in the browser exactly as I wish. However, it provides a filename of a series of numbers followed by=temp.pdf.
Is there any way to provide a variable name for the displayed file?
For example, if I provide a #URL.name# in my form submission, I would like the filename displayed in the browser to be smith.pdf or whatever name I place in the #URL.name#
I think this is what you need below. I once had to create a pdf document using cfdocument and I used the below to specify the filename to render as. The caveat is that i had to save the file on the file system first which i achieved with same cfdocument.
note path_to_pdf_file_on_server and name_to_render_as.pdf in the code below
<cfheader name="Content-Disposition" value="attachment;filename=name_to_render_as.pdf">
<cfcontent type="application/pdf" file="path_to_pdf_file_on_server" deletefile="Yes">
How can images be loaded into a dynamically generated pdf (cfdocument)? In that the pdf is not stored the hdd. The pdf needs to be emailed, and the ram cleared. The images are stored outside of the wwwroot folder.
If it is need be, the pdf can get stored in the hdd, get attached, emailed, then deleted, but would opt for it not to get stored in the hdd.
c:\coldFusion9\imgs\ is the dir
Sample:
<cfdocument format="PDF" localurl="true">
<cfoutput> #vars#</cfoutput>
</cfdocument>
I have used
<img src="">
inside cfdocument, and it works if the image is in the wwwroot (http...) folder, but not when the image is outsite the wwwroot ("c:\coldFusion9\imgs#image#.png" or "../imgs/#image#.png").
I suppose that cfcontent is ideal
So, inside cfdocument, I do this:
<cffile action="readbinary" file="c:\coldFusion9\imgs\#image#.png" variable="img">
<cfcontent type="image/jpg" variable="#img#" >
The result is that the image loads, on the screen, not the pdf.
Would like to email the pdf as an email attachement. The pdf does not need to render on screen, but for testing purposes, we could let it render on the screen to know if the image was loaded or not, by either naming or not naming the cfdocument. The pdf renders when the name is removed, it does not render when the name is present.
Appreciate your help.
If i understand your question correctly. You want to
1. Grab an image from a folder outside of your webroot
2. Place image in a cfdocument
3. Attach cfdocument to a cfmail
if that's is the case you need cfimage instead of img and the rest you can find on Ben Nadel's site http://www.bennadel.com/blog/1700-Ask-Ben-Creating-A-PDF-And-Attaching-It-To-An-Email-Using-ColdFusion.htm
or expand on the snippet below.
<cfdocument format="pdf" name="mydoc">
<cfimage action="writeTobrowser" source="c:\temp\test.png" >
</cfdocument>
<cfmail
from="x#y.com"
to="y#x.com"
subject="this is it">
<cfmailparam
file="mydoc.pdf"
type="application/pdf"
content="#mydoc#"/>
</cfmail>
A couple notes to clarify:
cfdocument uses an HTTP connection to grab images, which is why you can't grab any outside the webroot. In my experience, relative paths are problematic, so it's best to use absolute paths. If you want to use images from outside the webroot, you'll need to provide them directly, as in your example or as #KobbyPemson did.
The reason that you don't see the PDF when you add a name is that the name attribute does not name the PDF. It is the name of the variable in which the PDF is stored. So, when you provide it, you are telling CF to stuff the PDF in a variable using the name you supply.