|
 Thursday, April 19, 2007
« Unit Testing .NetTiers Processors with D... | Main | Good SharePoint HowTo Videos »

Forcing a download in ASP.NET - How and Why

I really did think this was something every ASP.NET Developer knew how to do. I'd also like to add that I was also under the assumption (which is false) that most all ASP.NET developers know the security risk associated with persisting sensitive (financial, personal, etc) information to a directory available to the web. The example I'm talking about is when a user views a report from their account online and they choose to "export" it for download, this export should NEVER EVER EVER be persisted on the disk (unless you have some major security backing it up or unless its getting deleted right away, but still, I dont recommened it).

I'm going to demonstrate how to force a download, and yes, I'm aware that this has been done by thousands of other sites already. The problem is, apparently there are not enough sites out there that stress the importance of this, so dont flame me for reiterating a supposed well known simple implementation. :) This fits into the same category as "why is your entire business logic in your code behind area", but thats another post, for another day.

The reason is, if we persist a file, lets call it "BobsFinancials.txt" to a directory called "Exports" in the website and then we give Bob a link to download it; he can download it, but so can everyone else. Lets say that "Susy" logs into the system, Susy is Bob's Ex-Girlfriend and she can't stand him, so she has it out for him. Susy knows that Bob uses the same bank as her so she knows that he has the same account screens she does. Susy performs a export for her own account, she see's the url is http://www.example.com/exports/SusysFinancials.txt . She is able to figure out (since she knows that Bob is a user on the system) that Bob's financials might also be in the "exports" folder. So she types in the url: http://www.example.com/exports/BobsFinancials.txt, and blammo, now she has Bobs information.

You'd be surprised how many times I've seen this happen. DOZENS upon DOZENS upon DOZENS. 

So, if we are not to persist the data to the disk, what are we to do? How can we give the data to the user?

HOW TO FORCE A DOWNLOAD AND NOT PERSIST

Well, the data has to come from somewhere, a datastore of some type. You have to build the export somehow (through code). And then you want to give it to the user. Here's how.

1. Buid your export (how ever you want, for example this could be a string of random data)

2. Send it to the user, by forcing a download. We will not be

We've all see it before the dialog box that has a "Save" button present. (Again, I was under the false impression that everyone knew how to do this.) So we need to force a download. In the background whats going on is that the report is stored in memory, we're going to take it from the server's memory and pass it directy to the user through the response stream.

Code

// textExportBuilder - A String Builder that was used to build the report.

sFileName = "BobsFinancials.txt";
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", sFileName));
Response.Write(textExportBuilder);
Response.End();

This code uses the AddHeader method of the Response Object to force the user to download the file. The file has not been saved to the server, it was generated on the fly and given to the user when they needed it and now its gone. There is no actual physical file persisted on the disk that other users can download.

This is a very simple, very beginner thing that A LOT of developers are not aware of.

#    Comments [1] |
Monday, May 12, 2008 6:00:44 AM (Eastern Standard Time, UTC-05:00)
Hi

I have tried this in my webpart and it works for the download, open and save. But if I close the new window and click on the following link to download the next file, there is no postback? If I refresh the page it works again.

Thanks
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview