Click here to Skip to main content
15,867,308 members
Articles / Web Development / ASP.NET
Tip/Trick

Tracking downloads using an HTTPHandler

Rate me:
Please Sign up or sign in to vote.
4.75/5 (4 votes)
15 Jan 2011CPOL2 min read 22.5K   15   2
Using an HTTPHandler to make calls to the business layer to update file download count.
Not long ago, I developed a freeware application and made it available on my site for download. In a short period of time, it has started to become somewhat popular, can tell by download stats on some of the other sites where I made it available so I wanted to be able to track the number of downloads of any of the files that were being downloaded from my site and this is the solution I came up with.

In the pipeline, the Handler is called last and when it is called, the appropriate HTTPHandler is executed. Since the HTTPApplication object will call the HTTPHandler to process the request and generate a response, we can use our handler to implement our call to the business layer to update the count for the file in question and fulfill the request for the download.

To accomplish this, I use a modified anchor tag instead of the usual anchor tag that makes a call to our handler like so:
//Old way
<a href="path_to_file.ext" />Some Text

//New way
<a href="DownloadHandler.ashx?file=path_to_file.ext" />Some Text

The code below is a copy of the handler code that I use on my site. I have read in many places that the handler needs to be registered in the Web.config file, but when I tried this it did not work, so I didn't register it and just call it as described above. The magic that makes this work is the few lines starting at the Content-Disposition which is the file name that is suggested in the File|Save As Dialog. Content-Length is the maximum size of the data to be transferred, caution do not set this value to low as it will end prematurely and the downloaded file will most likely be corrupt. Next, we tell it what we want to download and in this case the application/octet-stream specifies that it is a binary file and finally output the file using the context.Response.WriteFile.
C#
<%@ webhandler language="C#" class="DownloadHandler"; %>
using System;
using System.Web;
using System.Web.UI.HtmlControls;
using System.IO;
    public void ProcessRequest(HttpContext context)
    {
        //Retrieve file name from URL and append my downloads path
        string fileName = context.Request.QueryString["file"].ToString();
        string filePath = HttpContext.Current.Server.MapPath("~/downloads/" + fileName);
        //Be sure the file exists
        FileInfo file = new System.IO.FileInfo(filePath);
        if (!file.Exists)
        {
            context.Response.StatusCode = 500;
            context.Response.End();
            return;
        }
        //Call to business layer to update the count based on the filename
        DownloadsService.UpdateDownloadCount(fileName);
        //Don't allow response to be cached
        context.Response.Clear();
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.Cache.SetNoStore();
        context.Response.Cache.SetExpires(DateTime.MinValue);
        //The next few lines is what actually starts downloads the file.
        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
        context.Response.AddHeader("Content-Length", file.Length.ToString());
        context.Response.ContentType = "application/octet-stream";
        context.Response.WriteFile(file.FullName);
        context.ApplicationInstance.CompleteRequest();
        context.Response.End();
    }
    public bool ValidateParameters(HttpContext context)
    {
        return true;
    }
    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
United States United States
Currently enjoying retirement and working on projects without pressure, deadlines or any kind of management.

Comments and Discussions

 
GeneralReason for my vote of 5 Good one Mike, Nice share. Pin
thatraja4-Apr-11 6:52
professionalthatraja4-Apr-11 6:52 
GeneralReason for my vote of 5 Thanks for sharing this tip. Pin
linuxjr16-Jan-11 7:07
professionallinuxjr16-Jan-11 7:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.