views:

190

answers:

3

Working in an asp.net 2.0 (VB) environment, I already have code that can generate an excel file from a database for a particular "user" of the website. I want to be able to launch this report generator on demand, and then after the file has been generated, allow the user to download this file.

How can I do this securely, and not just dumping the files off in some publicly readable directory?

Note: Related to this question, but the part I'm really interested in was never answered.

+3  A: 

Instead of putting it in a public directory you could create an HTTP Handler which allows you to do authorization.

You can create an handler either by compiling and registering in web.config or by creating an ashx page. Then your page would authorize the user, and then write the contents to the response.

If you need session state be sure to inherit from IRequiresSessionState.

Edit

I'm a C# guy so here's a sample in that:

public class DownloadFile : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{

    public void ProcessRequest (HttpContext context) {
    //Validate user is authenticiated and authorized.
    if (context.Request.IsAuthenticated)
    {
         //This is your own custom authorization mechanism
         if (AuthorizeUser(context.Request.User))
         {
            //not sure what the correct content type is. This is probally wrong
            context.Response.ContentType = "application/xls";
            //Setting size is optional               
            context.Response.AddHeader("Content-Disposition",
               "attachment; filename=" + downloadName + "; size=" +               myExcellFile.Length.ToString());
            context.Response.BinaryWrite(myExcellFile);


         }

    }
JoshBerke
Fantastic! Thanks!
Jeffrey
+2  A: 

Use an Http handler (*.ashx file). Move your code to generate the file to the handler, check security there before generating the file, set the appropriate content-type and content-disposition headers, and use Response.BinaryWrite to send your file directly to the browser. Never put it on your server's file system.

Joel Coehoorn
Good point except if generating the file takes a long time, he might need a two step process.
JoshBerke
Some of these files that we generate are in the 60 second+ range.
Jeffrey
If you can calculate or estimate the size of the result, this is still the way to go because you can flush the response buffer periodically. This will get the file to user much faster and help keep less in memory in on disk for your server.
Joel Coehoorn
This is probably the slicker solution to this, but would require refactoring some code I would rather not mess with. Definitely interesting, and I may revisit this at some point. Thanks for the answer.
Jeffrey
A: 

Can you...?

  1. Create your excel file in a private (not accessible to the user) folder
  2. Return to the user a unique url that's associated with the excel spreadsheet (something that's not easy to guess)
  3. Process that url request in your app and stream the excel spreadsheet to the caller (changing the content type of the response accordingly)

This would allows you to have those urls time out or even to regenerate the excel spreadsheet on the fly if needed.

Martin Peck