I frequently get asked about providing links to files to be downloaded from ColdFusion websites. Many people will just create a direct link to the file that downloaded such as "myfile.pdf", but by doing it this way you have no control over how the end user's browser is going to access that file. Controlling how the end-users browser accesses the file is very simple with ColdFusion. This can be done in ten lines of code or less. And the benefit of doing it this way is you also mask the location on your file server where your downloaded files are stored. And by doing it this way you could even place these download files outside of the web root for even greater security.There isn't much to it just three tags; cfSet, cfHeader and cfContent. Create a new file and name it something like filedownload.cfm and copy the code below into that file and save it. The only thing you should have to do is modify the line that has "[ PATH TO YOUR FILES FOR DOWNLOAD ]" by setting the correct folder path. You should be able to test this by modifying the code that would normally have a link to the file and change the link to call this file and pass is the filename of the file to be downloaded. The link would should look like something like this: filedownload.cfm?filename=myfile.pdf.
<cfif StructKeyExists(url,"filename") && fileExists(folder & filename)>
<cfset filename = "#url.filename#">
<cfset fileInfo = GetFileInfo(folder & filename)>
<cfset mimeType = getPageContext().getServletContext().getMimeType(folder & filename)>
<cfheader name="Content-Disposition" value="attachment; filename=""#filename#""">
<cfheader name="Expires" value="#Now()#">
<cfheader name="Content-Length" value="#fileInfo.size#">
<cfcontent type="#mimeType#" file="#folder##filename#" deletefile="No">
So what am I doing here?
- Checking to make sure a filename was passed and that it exists!
- Getting the file size using getFileInfo.
- Getting the mime type using a little CF mixed with Java.
- Setting the header Content-Disposition. This is critical. By specifying the key word Attachment you will be forcing all browsers to download the file using the default download tool. If you specify 'Inline' you can force the browser to try to display the file inside the browser window. Since Internet Explorer can open many MS Office documents in the browser window you need to specify which you want to happen.
- Set the header Expire to now() so the browser will not cache the file.
- Specify the length of the content (ie file size) the the browsers download manager can correctly estimate the download time and amount remaining. A nice thing to do for your users when having them download large files.
- Delivering the file to the browser using cfContent. This also specifies the file mime type and file name so the browser download manager knows how to handle the file and the name it should use to save the file.
And that is how you should serve up a file to be downloaded using ColdFusion. It's quick and easy.
*Note: When I write little tools like this I'm usually writing it because there is something I absolutely need to see in order to complete another project. These little tools are not written as projects themselves and therefore may not be very pretty or as full featured as something that I was writing as a complete project. I just needed to get some code running that gave me back the data I needed to see. There are no warranties or promises. If you find is useful then great. If not, oh well. I know the code works on CF9 at the moment. I can not be certain if it still works on other versions of ColdFusion. * Any code posted may not be totally secure or production ready. Use at your own risk. ** Unless otherwise noted, this code shall be deemed Public Domain.