Introduction
This article demonstrates how to provide download of a file in ASP.net along with tracking its success and failure. It will be useful especially in e-commerce system that offers downloadable product option. In e-commerce system it is very important to keep track of status of download. For a download option there can be two scenarios 1.complete/success download and 2.failure download.
In e-commerce system user may have a limited number of download allowed which is one in most of the cases. If a download is successful, it should update the record which will indicate the user that he has already downloaded the file or increment the download count by 1. But for failure download the user should be able to download it again or the download count should remain same. So this article will help in tracking such status of download.
While working on a e-commerce project I had a requirement to implement such a functionality where the success/failure of the download can be tracked. After searching for the solution I found that there is no such article related to similar problem. Then I came up with this solution after reading an article on transferring file in small packets. I hope this solution will help others struggling with similar problem.
Basics about download
When the function provided is called on click of download button, a similar window as shown below opens asking the user to Open, Save or Cancel.
Clicking Open or Save will result in start of download where as Cancel will stop/fail the download.
A user can Cancel the Download even after Open or Save click, which need to be tracked.
The code involved
The
code contains the basic logic of File Download in ASP.NET, which will
not give end-user any hint of the location of the file. First we create System.IO.FileInfo
object providing the complete file path, which will give us the file length. We
also create a FileStream object which will be passed to BinaryReader object
which in tern will help reading the data into bytes. Then we use the Response
object to transfer the data.
//File Path and File Name string filePath = Server.MapPath("~/ApplicationData/DownloadableProducts"); string _DownloadableProductFileName = "DownloadableProduct_FileName.pdf"; System.IO.FileInfo FileName = new System.IO.FileInfo(filePath + "\\" + _DownloadableProductFileName); FileStream myFile = new FileStream(filePath + "\\" + _DownloadableProductFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Reads file as binary values BinaryReader _BinaryReader = new BinaryReader(myFile); long startBytes = 0; string lastUpdateTiemStamp = File.GetLastWriteTimeUtc(filePath).ToString("r"); string _EncodedData = HttpUtility.UrlEncode(_DownloadableProductFileName, Encoding.UTF8) + lastUpdateTiemStamp; //Clear the content of the response Response.Clear(); Response.Buffer = false; Response.AddHeader("Accept-Ranges", "bytes"); Response.AppendHeader("ETag", "\"" + _EncodedData +"\""); Response.AppendHeader("Last-Modified", lastUpdateTiemStamp); //Set the ContentType Response.ContentType = "application/octet-stream"; //Add the file name and attachment, which will force the open/cance/save dialog to show, to the header Response.AddHeader("Content-Disposition", "attachment;filename="+ FileName.Name); //Add the file size into the response header Response.AddHeader("Content-Length", (FileName.Length - startBytes).ToString()); Response.AddHeader("Connection", "Keep-Alive"); //Set the Content Encoding type Response.ContentEncoding = Encoding.UTF8; //Send data _BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);
There is no response coming back
from the download window whether download is completed or aborted in between so
it become more difficult to know the status of download. The Basic logic
behind tracking the download status is transferring the file into smaller
packets(size of packets can be kept as per convenience) and checking
whether all the packets has been transferred. If there will be any failure
in between the transfer of file total number of packets will be compared with
number of packets transferred. This comparison will decide the
status(Success/Failure) of download. For very small file it is difficult to
track failure of download as the number of packets will be very few. So
more effective tracking will happen if file size will be greater than 10kb.
In below code we are getting the
total number of packets by dividing total bytes of data by 1024 to keep the
packet size as 1kb. To send the data packets one by one we are using for
loop. Using Response.BinaryWrite we are sending the 1024 bytes of
data at a time which is read using BinaryReader.
//Dividing the data in 1024 bytes package int maxCount = (int)Math.Ceiling((FileName.Length - startBytes + 0.0) / 1024);
//Download in block of 1024 bytes int i; for(i=0; i < maxCount && Response.IsClientConnected; i++) {Response.BinaryWrite(_BinaryReader.ReadBytes(1024)); Respons.Flush(); }
Then we compare the number of data
packets transferred with total number of data packets which we calculated by
dividing file length by 1024. If both the parameters are equal that means that
file transfer is successful and all the packets got transferred. If number of
data packets transferred are less than total number of data packets that
indicates that there is some problem and transfer was not complete.
//compare packets transferred with total number of packets if (i < maxCount) return false; return true;
Close the Binary reader and File stream in final block.
//Close Binary reader and File stream _BinaryReader.Close(); myFile.Close();
About my company – Proteans Software Solutions
Proteans Software Solutions is an outsourcing company focusing on software product development and business application development on Microsoft Technology Platform. Committed to consistently deliver high-quality software products and services through continual improvement of our knowledge and practices focused on increased customer satisfaction.