Downloading Files In ASP.NET Using C#

In a previous article, I discussed with you how to allow users to upload files to the Server via ASP:fileupload control. You can see it here.

In this article, I will be discussing with you how to download the files from the Server. We will be creating a generic handler to do all the heavy lifting. In this way, the code can be re-used, whenever and wherever it is required.

As usual, I recommend creating a new Website to play around with. Hence, open up Visual Studio and create a new empty ASP.NET Website (File > new > website) or (Shift + Alt + N).

In your shiny new Website, we need to add a generic handler, so go to (website > add new item) or (Ctrl + Shift + A).

Select generic handler from the list.  I called mine download.ashx.

Visual Studio will do some of the hard work for you by generating the following:

  1. <%@ WebHandler Language="C#" Class="Download" %>  
  2.   
  3. using System;  
  4. using System.Web;  
  5.   
  6. public class Download : IHttpHandler {  
  7.       
  8.     public void ProcessRequest (HttpContext context) {  
  9.         context.Response.ContentType = "text/plain";  
  10.         context.Response.Write("Hello World");  
  11.     }  
  12.    
  13.     public bool IsReusable {  
  14.         get {  
  15.             return false;  
  16.         }  
  17.     }  
  18.   
  19. }  
Inside the process request part of the generated code, you will need to delete its current contents, i.e. these, lines:context.Response.ContentType = "text/plain"; context.Response.Write("Hello World");

Once, you have deleted those lines, add the following code:
  1. string file = context.Request.QueryString["file"];  
  2.   
  3. if (!string.IsNullOrEmpty(file) && File.Exists(context.Server.MapPath(file)))  
  4. {  
  5.     context.Response.Clear();  
  6.     context.Response.ContentType = "application/octet-stream";  
  7.     context.Response.AddHeader("content-disposition""attachment;filename=" + Path.GetFileName(file));  
  8.     context.Response.WriteFile(context.Server.MapPath(file));  
  9.     // This would be the ideal spot to collect some download statistics and / or tracking  
  10.     // also, you could implement other requests, such as delete the file after download  
  11.     context.Response.End();          
  12.   
  13. }  
  14. else  
  15. {  
  16.     context.Response.ContentType = "text/plain";  
  17.     context.Response.Write("File not be found!");  
  18.           
  19.   
  20. }
What does this code do? Well, I’m glad you asked. First, it creates a string from the query string value, which is the file to be downloaded by the user. Next, it checks to make sure the newly created string is not empty and the file exists. If it passes these checks, the code can move on but if the checks have not been passed, the code takes you to the else block, which informs the user that the file cannot be found.

Now, the interesting stuff happens. First, we clear the output before. We fill it in case there is any data lurking around in there that we’ve forgotten about. Next, we set the content type to ‘application/octet-stream’ which is a binary file. In this way, all the file types are covered. Subsequently, we move onto the next line, ‘AddHeader(("content-disposition", "attachment;filename=" + Path.GetFileName(file))’. This lets the user save the file on his computer and then decide how to use it, instead of the Browser trying to use the file. Next, we write the file and call Response.End(), which sends all currently buffered output to the client, stops execution of the page and raises the System.Web.HttpApplication.EndRequest event.

To use the generic handler we have just created; you will need to add a link into your Webform, as shown below:
  1. <a href="Download.ashx?file=images/cat1.jpg">cat pic</a>  
You can see your link in the download.ashx file with a query string that informs the code which file the user wishes to download. In this case, it is an image file called cat1.jpg, which resides in a folder called the images. It is easy to implement and the code can be reused. Wonderful isn’t it? Now, you can start offering some goodies to your website users.

I hope you found this article helpful and informative. If you have any comments, questions, queries etc. then please feel free to comment below or get in touch via email at michael@griffithswebdesign.com

I look forward to hearing your thoughts.