Implementing the content download feature in web applications

Recently I twitted on the idea that some ECM applications can’t even do a file download “right”, much less more esoteric features like social interaction enablement. Although that twit was a bit of a rant, it is fundamented by the fact that I’ve encoutered several applications (Webtop being one) in which downloading a file is sometimes a (technical) challenge and fails unexpectantly. But I digress…

As life always has a way of coming back at you.. the next day I’ve noticed a support issue on my team in which one of our customers complained that if it tries to download a dynamically generated file then a blank browser window appears and remains open. The download was ok, but the window was annoying. On IE6 only.

Want to bet what we were ready to say to the customer? “It’s IE6’s fault! Get rid of it or change a certain setting to make it work (which setting… nobody knows)”. Some call that the Russel Crowe move.

Remembering what I’ve just said publicly to the world and wanted to not be in the same category with the “ECM dudes which can’t implement a file download right”, I looked into the problem myself.

It’s a simple thing: downloading a secured file (dynamically generated or not, doesn’t matter).

Given the behaviour, my bet was that the team has done something like a javascript snippet with and that on the request the server returned actually a file to be downloaded not a web page. Firefox and IE7+ probably detect that the newly created window is useless and close it (or never create it in the first place). But IE6 is actually doing what you asked for.

Fired up Charles, looked into the app…. by the way, it’s an IceFaces app, which somehow will help my conclusion of the post. What I see there is exactly what was expected.

The application had a HTML button on it with some JavaScript code behind (coming through the IceFaces intricate ways) which did a wonderful with target _blank. The URL of the window was actually a servlet which returned the content stream. Isn’t that cute?

So, I advised the team to go back to the old school ways of putting that URL into a HTML <A> tag and get it over with.

Strange thing happened: the team decided to try and still use Javascript (yes, we love Buttons very much) and try location.href in order to direct the browser into downloading the file. This approach worked in IE6. Tada! But in IE8 for example it generated one of the famous yellow warning bars on top of the page (yes, the one a user will for sure ignore or dismiss bluntly) saying “This website tries to download a file. Allow it? If yes, please right click, jump though 7 hoops, hold you breath 5 seconds, refresh the page and click on the button again. Thank you”.

So location.href does not work either (although it has that interesting result, I always wondered how that was done…now I know).

What about the old school <A HREF=””> tag? Yes, that works. Flawlessly. Simple, clean and nice.

PS: if someone wishes to see a “button” not a text link, just enclose a IMG, border=0 with A. Add CSS to simulate on hover changes and be done with it (sorry to say such trivial things, but I think it helps).

Ok, so here is how to properly (in my opinion) implement a file download action:

– use <A> and target it to the URL of a server side script/servlet/something which returns the content

– the server side should return something like this:

Cache-Control: max-age=0

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Content-Type: application/octect-stream;charset=UTF-8

Content-Disposition: attachment; filename=”blah blah blah.xls”

A few “thumb” rules here:

– Always put Content-Type response header before Content-Disposition header. Some browsers have a problem with a reversed order.

– the filename must be enclosed in quotes. If you don’t, some (most) browsers will not display the proper name of the file to be dowloaded

– be careful of the spaces, colons and quotes int the content-disposition header. they matter

– in IE6 the content-disposition header can’t be too large

Some reading to be done to understand the above:

Read here:

And here:

And here:

And here:

And here:

I hope this helps. And please, dev guyz & galz… don’t follow the easy path of web frameworks (eg. IceFaces) on all counts. Going back to the roots is not that bad and keeps your software resilient.


Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s