Have you ever gone to a site that provides file downloads, but when you click the "Download Now" link, it servers up an intermediary page that says your file will be begin downloading shortly; and then, as if magically, seconds later, it prompts you for the file download. Most of the time, if you look at the source code to that page, you will find that there are no Javascript timeouts or Meta tag refreshes. So, how does page automagically server up a delayed file?
The magic lies in the page headers that get sent as the first pieces of content to the client browser. Page headers, while invisible to the end user, contain a ton of useful information and processing suggestions that change the way the browser will act. In this case, the page header we need to look at is the "refresh" command. The refresh header tells the client to refresh to a new location (URL) after a given delay (in seconds).
To demonstrate this, let's take a look at the pages involved. First, we need the page that provides a link to the file download:
Launch code in new window » Download code as text file »
This file does nothing else except take the user to the following page where the delayed download takes place. In our example, the file being downloaded is hard coded into the logic, but this is something could easily be passed in the URL as a file ID or some encrypted value:
Launch code in new window » Download code as text file »
This page will be displayed for 2 seconds before the browser gets taken to the target file (red_hot.jpg). The trick here is the two modes the page is running in. Notice that we are defining the URL value, download. If this is false (which it is by default) then we display the intermediary download page. If this value if true then we either take the user to the target file or prompt them for download.
If the download value is false, meaning we are going to display the intermediary page, we set the refresh command using the ColdFusion CFHeader tag. This will set a header value to be sent to the client browser, in this case a 2 second pause followed by a forwarding to the url, ./download.cfm?download=1. This will take use back to the same page but with a different URL.download value. All header values must be set before any content is flushed to the client (as headers are and can only be the first pieces of data sent to the client).
In this demo, I am using CFLocation to forward the user to the target file. This is the easiest solution and puts much less strain on the ColdFusion server since the actual file transfer is handled by IIS. It does, however, require that the target files be web-accessible since CFLocation can only go to public URLs. CFHeader / CFContent, on the other hand, give you much more control over how the file is handled (inline vs. attachment, suggested file name) and where the files can be located (in a private folder), but they require that ColdFusion handle the file transfer, which can be a drain since it ties of processing power.
Download Code Snippet ZIP File
Comments (9) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
Learning ColdFusion 8: Defining Tags With AttributeCollection
Lenny And Bo, ColdFusion Programmers (Vol. 16)
Very cool Ben. Thats a great tip.
Posted by Rey Bango on Jun 5, 2007 at 11:45 AM
@Rey,
Thanks. It was something that I didn't think about very much, so I figured I would touch on the topic.
Posted by Ben Nadel on Jun 5, 2007 at 2:04 PM
Neat but why? He he. I was always annoyed at sites that did that. Does it really serve a purpose? Just give me the damn file...I don't want to wait. Just a small rant I guess.
Posted by Boyan on Jun 6, 2007 at 9:14 AM
@Boyan,
No idea why pages do that... my only guess is that it gives them another chance to server up a page with advertising on it :)
Posted by Ben Nadel on Jun 6, 2007 at 9:27 AM
Ben, could the same strategy be used for a "waiting to process" page? For example, www.orbitz.com when you search for flights. Sometimes, it takes up to 1-2 minutes before the system returns...but while you are waiting you are getting a nice "Please wait while we find your flights..." message.
Or is that another whole ball of wax?
Posted by Ryan Chittenden on Jun 9, 2007 at 7:32 PM
@Ryan,
I think the same process can be applied there, most definitely. If you know that the processing page can take a long time, send the user first to an intermediary page that loads instantly (or just about) and then you can use the same Header / Location technique to take the user to the processing page. The only real difference, as I can see it, would be that you would have to send more variables via the URL; where we had just a download action flag, you would need to send through all the search criteria.
Posted by Ben Nadel on Jun 9, 2007 at 8:12 PM
We've adapted this CFM solution to PHP. We use the intermediate page to notify the users that the security settings of the file's target Microsoft application needs to be altered for the files to operate correctly.
Posted by G Calabrese on Sep 14, 2007 at 11:54 AM
@G Calabrese,
That is a cool use for it. I didn't even think of anything like that.
Posted by Ben Nadel on Sep 14, 2007 at 11:57 AM
Can i redirect to another page after the download prompt? I have it set up with the cfcontent/header verbage, but the <cflocation> tag i have after that doesn't seem to execute.
Posted by Dustin on Mar 19, 2008 at 5:21 PM