jQuery File Download is a cross server platform compatible jQuery plugin that allows for an Ajax-like file download experience that isn’t normally possible using the web.
- Brings control back to the developer by exposing a “successCallback” and “failCallback” that allows the developer to control the user experience in either situation.
- In conjunction with jQuery UI a developer can easily show a modal telling the user that a file download is occurring, disband the modal after the download starts or even inform the user in a friendly manner that an error has occurred. See the Demo for an example of this.
- File downloads don’t occur in the current window’s location bar. This means if a failure or something unexpected happens the user doesn’t leave the current page they are on or even have to see an ugly error message. This is critical for a good user experience especially on a highly Ajax application.
A classic problem with browser file downloads – Error handling
When the response comes back the HTTP response headers can contain many different things (in fact almost anything). Here are some examples:
Normal, HTML Response
The above “Content-Type” indicates to the browser that it should parse the DOM in the response and display it to the user. The location in the user’s location bar changes to reflect the address of the just-downloaded content.
Normal, “File Download” Response
The above “Content-Disposition” indicates to the browser that the server is trying to invoke a file download in the browser. The browser responds by opening up a file download dialog (or ribbon) for the user to download the file. As a convenience when the browser detects a response like this it doesn’t change the address bar so effectively the user stays on the same page.
Failed, “File Download” Response
As you may have guessed from that ugly highlighter color we’ve got trouble here. The response from a file download error is generally no different from a normal HTML response, the only difference here is that is has an error message as HTML content. The browser will now happily replace your existing page and address with the new error message. Not only have we now displayed an ugly error message to the user but we have also caused them to leave whatever page they were on.
Imagine you have created a nearly exclusively Ajax site like Gmail. A response like this from the server will cause your entire DOM to be replaced by an error message. Imagine this happening to you in Gmail and having to load up everything all over again. Ouch! My current role creating the framework for a highly Ajax application (like Gmail) inspired me to write this plugin for all to use – “web applications” is where the web is going anyways so there has to be a better way…
Another classic problem with browser file downloads – “Happy path” user experience
I probably just caught you thinking this: “well so what… my site never has any problems that cause error messages”… fair enough, but consider this:
- What is the response time of your web site in terms of serving up static files? Is it instantaneous? Is a user going to immediately look in the far corners of their screen for some sort of a spinning indicator or might they get confused or angry based on their technical prowess? Maybe they are looking at one of these? http://www.ict.griffith.edu.au/images/Animation/netscape_anim.gif (I hope not or you’ve got bigger issues)
- What if you are serving up a dynamically generated file (perhaps a report of SQL data?) based on user input that may take a few seconds. An average user might expect some sort of indication of what is going on. At the very least from a developer’s perspective it’d be nice if it wasn’t easy for them to hammer the download link a few times (to make it faster of course) wasting cycles across an entire n-tiered application.
I’ve got a solution… just use Ajax to download it!
Good idea! Unfortunately this is not possible due to one key problem:
You can certainly use an XMLHttpRequest object to download a binary (or otherwise) file but there is nothing you can do to the response to somehow get it saved on the user’s computer. Flash doesn’t have this limitation, but we really don’t want to get into Flash do we?
Enter jQuery File Download
jQuery File Download overcomes all of the aforementioned limitations of a “normal” browser file downloads. Well how the heck does that work? The concept is nothing new in fact: If you browse around the web you will find plenty of forum posts discussing the same technique, I just wasn’t able to find a succinct easy to use plug-in to do it hence my decision to create this plugin. The answer is:
An iframe and cookie
What?! I have to rely on Web .1 technology to make my Web 2.0 Ajax application user friendly? Turns out this is the magic bullet combination to work around normal limitations of file downloads, here’s how:
An iframe (which is generally a mortal sin of modern web development) can exist in a DOM but in most respects is treated like an entirely different window. By dynamically inserting a hidden iframe into the DOM and setting its location to the desired file path we can initiate a file download just like it was occurring in the main application window. This directly gets us around one of the nasties of file downloads – if an error occurs the user has now been forced off of the page they were on (which may contain an Ajax application like Gmail) to see an ugly error message.
Like a normal file download in the main window an iframe will never fill with content when a successful file download occurs. It simply contains an empty DOM. Well how do we detect what is going on if nothing happens when the file download is successful. Well this is where the cookie comes in:
cookie + iframe
Since the creation of cookies exists in HTTP headers, which is standard fare for all web requests and responses, we can actually write a cookie to indicate that a file download has been initiated properly (instead of an error page). The response from the web server will now look something like this:
While we can’t directly tell if a file download has occurred we can check for the existence of a cookie which is exactly how jQuery File Download works. Once a download is initiated on the iframe a configurable duration poll of cookies and the iframe contents occurs. If the iframe fills with contents then we know a file download has occurred (in most cases, make sure to set a MIME type!). If the cookie gets written then we know to stop polling and kill the iframe because the file download dialog/ribbon has been displayed.
jQuery File Download is easy to use in the simple case but also allows for various callback options as well. Don’t forget to add the required cookie code in the next section!
Very simple code demo
Use of the very simple approach only protects you from the page changing in the event of a file download error. This alone is pretty useful. If an error occurs the user gets an alert() dialog that says “A file download error has occurred, please try again.” You can see this demoed here under the “Barebones – jquery.fileDownload.js” heading. I wouldn’t recommend using this option given a much better experience is only a few more lines away…
Impractical code demo of commonly used features
This just demos what you could do but I’d highly recommend against it unless you want confused and annoyed users. This will result in an alert() dialog telling you a file download initiation has just occurred for the specified URL. If a failure occurred it will display the attempted URL and error message in a dialog.
Simple rich user experience code demo
You can see this one running at the top of the demo page. In order for the below code to work for you, you will also need jQuery UI installed and an image (if you want) as a downloading spinner.
This code will cause any <a> with class=”fileDownload” like below
- User is informed of a pending report download via a jQuery UI modal that says “We are preparing your report, please wait…”
- Modal goes away just as the browser’s file download dialog/ribbon occurs
- User is informed of an error in a jQuery UI modal: “There was a problem generating your report, please try again.”
Custom rich user experience code demo
This demo does almost the same thing as above but handles the modals manually by using the callbacks and it uses modal HTML that already exists on the page.
HTML for jQuery UI Modals (place anywhere on page)
Using jQuery File Download – Server Code for Cookie
Only the MVC 3 server code has been tested. Actually if you want to see it running just head over to the demo page. Just make sure to write a cookie in the same HTTP response as the file download occurs with, that results in this HTTP Response Header (using default configuration):
ASP.NET MVC 3
If you are using a Controller Action to serve up your files (I hope you are!) you can very easily enable automatic cookie writing by inheriting your Controllers from a base class that writes the cookie automatically for you. This assumes that you are using MVC helpers for returning “FileResult”s (or derived classes like FileStreamResult). MVC FTW.
PHP (with example file)
Let me know if you have any issues or can think of some nice features to add.
Related newsQuest para se tornar ferreiro ragnarok
Izdihar riyadh compound accommodation
Legumes grelhados na churrasqueira bairrada
Zestra moda feminina vera
Gardenstown holiday accommodation
Esquerda e direita politico brasileiro
O que vestir no inverno do canada
Grupo r nv consultoria de moda