danielhordern.com

Logging Downloads

I am interested in keeping track of the number of times something is downloaded from a site - potentially expanding the feature in the future to track number of downloads per-day etc. This comes under the heading of "Im sure this has been done before, and probably done better, however this is how I did it"

Overview

  • Modify any links to downloadable items replacing the direct url of the downloadable item with an ASP page and an ID (instead of http://www.danielhordern.com/downloads/something.zip with http://www.danielhordern.com/downloadstats.asp?id=1)
  • DownloadStats.asp will retrieve the id param and look up a matching record in a database table
  • The filename / path details will be extracted, the record count will be updated and the file sent back to the client browser

 

1) Database

A table (named Downloads) was created with the following attributes, DownloadID being the primary key.

Notes:

  • My working version has an extra field (MembershipLevel) allowing for support of username / password protected downloads
  • A more comprehensive solution would move DownloadCount into another table that logged all counts either with a time/date stamp, or grouped by date
FieldData type
IDAutonumber
PathText:200
FilenameText:200
DownloadCountNumber:Long Integer

 

2) DownloadStats.asp

<%@ Language=JavaScript %>
<%

    //Ensure that this page is not cached.
    Response.Expires = 0;

//-------------------------------------------------------------------
// global & constants
//-------------------------------------------------------------------

// this is typically defined elsewhere in your site (config.asp?)
//
var g_DBConnectionStr = 'Provider=Microsoft.Jet.OLEDB.4.0; Data Source=d:\sites\yoursite\databases\db.mdb';
      
    // wrap in function to hide local vars
    function doPage()
    {
            
        var id = _Safe_GetQueryStr('id');
        
        if( id == 'undefined' )
            id = '';

        _DownloadFile( id );
    }
    doPage();


    
    
    function _DownloadFile( Id )
    {
    var downloadPath = '';

        try
        {
            var sqlStr = 'SELECT Downloads.Path, Downloads.Filename, Downloads.MemberLevel FROM Downloads ';
         sqlStr    += 'WHERE Downloads.ID=' + Id;

            var oConnection = db_OpenConnection( g_DBConnectionStr );
            var oRs = db_OpenRecordset( oConnection, sqlStr );
            var oDate = new Date();
            
           if (!oRs.EOF)
           {
               if( oRs('MemberLevel').value == 0 )
               {
                downloadPath = oRs('Path').value + oRs('Filename').value ;
                 // clean up
                //
                db_CloseRecordset( oRs );
                oRs = undefined;       
                
                // and search for Id in LinkStats table
                //      
                sqlStr = 'SELECT DownloadStats.ID, DownloadStats.Date, DownloadStats.Count FROM DownloadStats ';
                sqlStr += 'WHERE DownloadStats.ID=' + Id + ' AND DownloadStats.Date=' + db_WrapDate(oDate.formatMediumDMY());
                oRs = db_OpenRecordset( oConnection, sqlStr, adOpenDynamic, adLockOptimistic );
                if( !oRs.EOF )
                {
                   oRs('Count')++;
                }
                else
                {
                   oRs.AddNew();
                   oRs.Fields('ID').Value = Id;
                   oRs.Fields('Date').Value = oDate.formatMediumDMY();
                   oRs.Fields('Count').Value = 1;
                }
                // update record
                oRs.Update();
                // clean up
                db_CloseConnection( oConnection, oRs );
               oRs = undefined;
               oConnection = undefined;

                    // redirect
               Response.Redirect( downloadPath );
               // no more script
               Response.End();
            }
         }
        }
        catch(e)
        {
            Response.Write('_DownloadFile(): ' + e.description + '<br>');
        }
    }
    
    
    
    /***************************************************************************
    
       extracted from utils/utils.asp
       returns request value as string
    
     ****************************************************************************/
    
    function _Safe_GetQueryStr( Key )
    {
        var str = '';
        if( Request(Key).Count == 1)
        {
            str = new String(Request(Key));
        }
        return str;
    }
    
    
    /***************************************************************************
    
       external functions used from utils/database.asp
       write replacements or copy from database.asp article
        
       ConnectionObj   function db_OpenConnection( ConnectionStr )
                       function db_CloseConnection( ConnectionObj, RecordsetObj )
       RecordsetObj    function db_OpenRecordset( ConnectionObj, SqlStr, CursorType, LockType )
                       function db_CloseRecordset ( RecordsetObj )
      
     ****************************************************************************/
%>