Asp.net: File Download Handler

Recently I had the need to make a file download page where statistics could be collected and saved on each individual download. After a little research I found a nice way to get this task done easily.

Because it is only collecting stats about the download and then sending the file to the browser, I decided to use an Asp.net Generic Handler.


Download.ashx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
 
namespace WriteFileTest
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Download : IHttpHandler
    {
 
        private string FilesPath
        {
            get
            {
                return @"C:\Users\John Boker\Documents\Visual Studio 2008\Projects\WriteFileTest\Files\";
            }
        }
 
        public void ProcessRequest(HttpContext context)
        {
            string filename = context.Request.QueryString["file"];
            if (!string.IsNullOrEmpty(filename) && File.Exists(FilesPath + filename))
            {
                context.Response.ContentType = "application/octet-stream";
                context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", filename));
                context.Response.WriteFile(FilesPath + filename);
            }
            else
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write("Invalid filename");
            }
        }
 
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

One advantage to this method is the files do not have to be in the website directories and public, extra authentication can be done and the download can be disallowed if necessary.


To test this i created a small Default.aspx page containing:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WriteFileTest._Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <a href="Download.ashx?file=FileZilla_3.3.0.1_win32-setup.exe&d=<%= DateTime.Now.Ticks %>">FileZilla_3.3.0.1_win32-setup.exe</a>
        <br />
        <a href="Download.ashx?file=gimp-2.6.7-i686-setup.exe&d=<%= DateTime.Now.Ticks %>">gimp-2.6.7-i686-setup.exe</a>
        <br />
        <a href="Download.ashx?file=jdk-6u17-windows-x64.exe&d=<%= DateTime.Now.Ticks %>">jdk-6u17-windows-x64.exe</a>
        <br />
        <a href="Download.ashx?file=WampServer2.0i.exe&d=<%= DateTime.Now.Ticks %>">WampServer2.0i.exe</a>
    </div>
    </form>
</body>
</html>

As you can see i added another argument to the QueryString; this is to keep the browser from caching files with the same link and filename.

WriteFile Default Page Image

The results after clicking the filezilla link:

WriteFile Save Dialog

This was a very simple method to take care of multiple issues including:

  1. Download Tracking
  2. Alternate File Locations
  3. Browser Caching Issues
  4. Extra Authentication

AttachmentSize
WriteFileTest.zip10.21 KB
Your rating: None Average: 5 (5 votes)

Comments

I doubt that even Jon Skeet

5

I doubt that even Jon Skeet himself could put together something this clean and elegant.

Jon Skeet would write this

Jon Skeet would write this with two lines of code with each line no longer than 8 characters.

Post new comment

The content of this field is kept private and will not be shown publicly.
 
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <c>, <cpp>, <csharp>, <css>, <drupal5>, <drupal6>, <java>, <javascript>, <objc>, <php>, <python>, <ruby>, <tsql>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.