Welcome to DotNetManiac

Http Handler: File download handler

Date Revised: August 13 2009

Visual Studio 2008 | C#

MIME allows your web browser to automatically display content of most common files like jpeg images and pdf documents but sometimes web developers like to be able to give users a choice of opening a file with its default viewer or choose to download it for use at a later time. Good news is that it's easy to solve this problem in asp.net by building your own file handler to give the user a choice. Here's how it's done: Right click on your web and choose "add new item", then choose "Generic handler", and finally add the following code. Additional mime types can easily be added, this link may help: www.webmaster-toolkit.com/mime-types.shtml

Click the link to see a live demo and download the code for this handler in a text file.

download Download code

<%@ WebHandler Language="C#" Class="FileDownloadHandler" %>
using System;
using System.Web;
 
/// <summary>
/// March 30 2007 - Created
/// August 13 2009 - Revised
/// 
/// Will force downloads for common files such as images, and documents that we don't want to 
/// open with the web browser.
/// Requires the complete virtual file path as querystring; filename=/images/x.jpg
/// 
/// Make sure the file exists before you send it to this page.
/// 
/// Resources: http://www.webmaster-toolkit.com/mime-types.shtml
/// </summary>
public class FileDownloadHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        try
        {
            string filename = context.Request.QueryString["filename"];
 
            if (string.IsNullOrEmpty(filename) ||
                !System.IO.File.Exists(context.Server.MapPath(filename)))
            { throw new System.IO.FileNotFoundException("File not found."); }
            else
            {
                // only allow certain file types
                string contentType = string.Empty;
                System.IO.FileInfo fi = new System.IO.FileInfo(context.Server.MapPath(filename));
                switch (fi.Extension.ToLower())
                {
                    case ".jpg":
                        contentType = "image/jpeg";
                        break;
                    case ".doc":
                        contentType = "application/msword";
                        break;
                    case ".pdf":
                        contentType = "application/pdf";
                        break;
                    case ".txt":
                        contentType = "text/plain";
                        break;
                    default:
                        // do not allow any other files to be downloaded
                        throw new System.ArgumentException(fi.Extension + " is not valid.");
                }
 
                context.Response.Clear(); // The Response.Clear method can be used to remove the buffer HTML output
                context.Response.ContentType = contentType;
                context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + fi.Name);
                context.Response.Flush(); // The Flush method immediately sends all current buffered page content to the client 
 
                // Writes the specified file directly to an HTTP response output stream without buffering it in memory.
                context.Response.TransmitFile(filename);
 
                context.Response.End();
            }
 
        }
        catch (System.IO.FileNotFoundException fnf)
        { context.Response.Write(fnf.Message); }
        catch (System.ArgumentException ae)
        { context.Response.Write(ae.Message); }
    }
 
    public bool IsReusable
    { get { return false; } }
 
}
Welcome to DotNetManiac