Click here to Skip to main content
Click here to Skip to main content

Tracking downloads using an HTTPHandler

, 15 Jan 2011
Rate this:
Please Sign up or sign in to vote.
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.
<%@ 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)

Share

About the Author

Mike Hankey
Retired
United States United States
I'm an old assembler and C programmer self taught in the object oriented languages and Web design. Upon graduating from Murray State University in 1983 I Started doing embedded systems for the automotive industry, got a wild hair and moved to Florida in 1986 and did some work on DEC PDP and MicroVax computers.
My latest project:
ToDoManager extension for VS2010 and Atmel Studio 6.1

Comments and Discussions

 
GeneralReason for my vote of 5 Good one Mike, Nice share. Pinmvpthatraja4-Apr-11 6:52 
GeneralReason for my vote of 5 Thanks for sharing this tip. Pinmemberlinuxjr16-Jan-11 7:07 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 16 Jan 2011
Article Copyright 2011 by Mike Hankey
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid