Meditation and Mindfulness for Software / IT Professionals. Conducted by Bipin Joshi in Thane. Read more...

<%@ Page %>

Tracking File Downloads

Introduction

If you run a web site that allows visitors to download some kind of files (ZIP, DOC etc.) then you may probably also want to track how many visitors downloaded the file. Such data is provided by sophisticated web site monitoring tools but if you do have use one, you can develop your own mechanism to do so. In this article I will show you how to track such downloads using ASP.NET and SQL Server. Note that the concepts explained here are applicable to web applications developed using other languages/scripts such as ASP.

Sample Scenario

We will develop a sample application that tracks the file downloads. The details of files are stored in a SQL Server database. Visitors see a list of files available for download in a DataGrid. When they select any file to download, the download count is incremented by one. The user then sees a normal file download dialog where he can choose whether to save the file or open it in associated application.

Database Table

In order to work with our example you will need a SQL Server database table named Files with following schema:
Column Name Datatype
ID Numeric (Identity)
FilePath Varchar(255)
DownloadCount Numeric

Displaying List of Files

Now we will develop a web form (say FileList.aspx) that presents the list of file to the user. Put a DataGrid on the web form and add a template column to it. Write following code in the code behind file of the web form.
private void Page_Load(object sender, System.EventArgs e)
{
	if(!Page.IsPostBack)
	{
		BindGrid();
	}
}

private void BindGrid()
{
	SqlConnection cnn=
	new SqlConnection("connection_string");
	SqlDataAdapter da=
	new SqlDataAdapter("select * from files",cnn);
	DataSet ds=new DataSet();
	da.Fill(ds);
	DataGrid1.DataSource=ds;
	DataGrid1.DataBind();
}
Here, we are simply binding the DataGrid with the records from files table. You need to replace the "connection_string" above with your own connection string. The DataGrid has only one template column whose markup looks as follows:
<asp:TemplateColumn HeaderText="Select file to download:">
<ItemTemplate>
<asp:HyperLink id=HyperLink1 runat="server" 
NavigateUrl='<%# "downloadfile.aspx?id=" 
+ ((DataRowView)((DataGridItem)Container).
DataItem)["id"] %>'>
<%#((DataRowView)((DataGridItem)Container).
DataItem)["filename"] %>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
Here, as you can see we have a template column that contains a HyperLink. The NavigateUrl of the HyperLink is set to another web form called downloadfile.aspx that actually tracks the download. We pass the id of the selected file to the web form.

Storing Download Count

The downloadfile.aspx web form simply contains following code in the Page_Load event handler:
private void Page_Load(object sender, System.EventArgs e)
{
	string fileid="";
	if(Request.QueryString["id"]!=null)
		fileid=Request.QueryString["id"];
	SqlConnection cnn=
	new SqlConnection("connection_string");
	SqlCommand cmd=
	new SqlCommand("select filepath from files 
	where id=" + fileid,cnn);
	object filename=cmd.ExecuteScalar();
	
	cmd.CommandText="update files 
	set downloadcount=downloadcount+1 
	where id=" + fileid;
	cmd.ExecuteNonQuery();
	
	FileStream fs=
	File.OpenRead(Server.MapPath(filename.ToString()));
	byte[] data=new byte[fs.Length];
	fs.Read(data,0,(int)fs.Length);
	Response.Clear();
	Response.AddHeader("Content-Type", "application/winword");
	Response.AddHeader("Content-Disposition",
	"inline;filename=sample.doc");
	Response.BinaryWrite(data);
}
Here, we simply fetch the file name of the file to be downloaded. We then increment the download count of the file by 1 using an UPDATE query. Next, we open the file for reading and read all the contents into a byte array. We then clear the response stream and add two response headers - Content-Type and Content-Disposition. The former tells browser about the MIME type of content (word document in our case) and the later specifies how it is treated while downloading. The "inline" specifies that the file to be downloaded in the same browser window and "filename" specifies the name of file to be displayed in the Save As dialog. Finally we send all the contents of the file to the browser using Response.BinaryWrite method. We used this method so that we can download any type of file such as text, graphics and binary.

You could have also use Response.Redirect to directly navigate to the required file but above technique gives more control on the process. You can easily modify the code if your files are stored in database itself. You also get chance to set the default download file name and finally you can hide the actual URL of the file that is being downloaded so that user can not directly navigate to the file bypassing the tracking mechanism.




Bipin Joshi is a software consultant, an author and a yoga mentor having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Meditation to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 22 Feb 2003



Tags : ASP.NET Web Forms Administration