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 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; } }
}