Introduction
This article gives readers a fair idea of how to create a progress bar while uploading single/multiple files in a web based application. We had a requirement in one of our projects for displaying a continuous progress bar along with percentage uploaded. This article will provide you great information about how to create such a control using ASP.NET 2.0 and .NET Framework 2.0. Also, the page on which this control is deployed will not be posted back as the solution uses an IFrame to load the file upload control. Users are free to access other parts of the page while the upload is still in progress.
Background
My initial idea was to calculate the progress amount on the server side and use a JavaScript timer function to read the server-side progress amount, with the XMLHttpRequest
object to update the progress bar from the client side. That didn't go well, as it shows either a 0% or a complete 100%, but not continuous progress. I used Mozilla Firebug to trace out the XMLHttpRequest
object requesting pattern. For some reason, XMLHttpRequest
s are queued until the server-side event handler finishes its execution, in this case, the upload, so either it hits before the server-side upload started, or after the server-side upload is completed. Hence the progress bar either shows 0 or 100%.
I would like to say thanks to Mr. Munur Shaik: http://www.c-sharpcorner.com/UploadFile/munnamax/ProgressBar07062007122251PM/ProgressBar.aspx for the idea, which I have reused for creating my progress bar. Also, I would like to convey my thanks to our architect Anil Sistla for supporting me in completing the solution. I hope this article will definitely save a lot of time for those who are looking for a similar solution.
Using the code
Shown below is the source code structure. The UploadProgressBar.ascx file is the user control that displays a single file upload control with Add/Remove buttons. The Add button adds the multiple file upload controls, whereas Remove clears the file upload controls one at a time.
The image below shows the initial file upload screen. FileUploadIframe.aspx contains a simple HTML IFrame tag to load the control page (FileUpload.aspx). Here, IFrame is used because the main page on which the multi-file upload is placed should not postback when the Upload button is pressed.
During file upload, the progress bar looks like below:
Below is the code for creating the progress bar:
public void CreateProgress(HttpFileCollection fileCollection)
{
StringBuilder sbProgress = new StringBuilder();
sbProgress.Append("<html><head><LINK REL=StyleSheet " +
"HREF='StyleSheet1.css' TYPE='text/css' /></head> <body>");
sbProgress.Append("<script src='JScript1.js' type='text/javascript'>" +
"</script><table id='mainTable' border='1'>");
for (int i = 0; i < fileCollection.Count; i++)
{
string strProgressBarId = "progressBar" + i;
string strPercentageId = "percentage" + i;
string fileName = fileCollection[i].FileName;
sbProgress.Append("<tr><td><p>" + fileName +
"</p></td><td><div id='xxx' " +
"style='background-color:White; width: 100px;height:15px; " +
"border-color:Black;border-width:thin;border-style:solid'>");
sbProgress.Append("<div class='progressBar' id='" +
strProgressBarId + "' ></div></div></td>" +
"<td><p><div id='" + strPercentageId +
"'></div></p></td></tr>");
}
sbProgress.Append("</table>");
for (int i = 0; i < fileCollection.Count; i++)
{
sbProgress.Append("<script type='text/javascript'> " +
"SetProgressBarProgressAmount(" + i + ",0 );</script>");
}
sbProgress.Append(PrepareTheGridHtml());
sbProgress.Append("</body></html>");
HttpContext.Current.Response.Write(sbProgress.ToString());
HttpContext.Current.Response.Flush();
}
This method (CreateProgress()
) basically pumps the progress bar HTML to the output stream to create an empty progress bar. In the above code, SetProgressBarProgressAmount(..)
is a JavaScript method which takes two parameters: the first parameter is the ID of the progress bar, which is necessary in case multiple progress bars are displayed, and the second parameter is the progress amount. As the file downloads to the server, this progress bar will be set as per the percentage of download, and finally, when the file download completes, it will be set to 100%. In the case of multiple file uploads, multiple progress bars will be displayed, one per each file, and the files will be uploaded to the server one by one, and we can see the progress amount of each file. Below is the code which downloads the file to the server:
public void DownloadTheFileToServer(HttpPostedFile file, int id)
{
Stream stream = null;
FileStream fs = null;
#region File Download Code goes here
try
{
string strFileName = System.IO.Path.GetFileName(file.FileName);
int contentLength = file.ContentLength;
stream = file.InputStream;
long totalUploadSize = stream.Length;
int bufferSize = 0;
if (totalUploadSize <= 1024)
{
bufferSize = 1024;
}
else if (bufferSize <= 4096)
{
bufferSize = 4096;
}
else if (bufferSize <=8192)
{
bufferSize = 8192;
}
else
{
bufferSize = 16384;
}
byte[] b = new byte[1024];
int tripDownloadSize = 0;
long totalDownloadedSize = 0;
float Percentage = 0;
bool isNewFile = true;
string fileStoreLocation =
ConfigurationManager.AppSettings["FileStoreLocation"];
fs = new FileStream(fileStoreLocation + strFileName, FileMode.Append);
while ((tripDownloadSize = stream.Read(b, 0, 1024)) > 0)
{
fs.Write(b, 0, tripDownloadSize);
totalDownloadedSize += tripDownloadSize;
Percentage = (int)(totalDownloadedSize * 100) / totalUploadSize;
setProgressBar(id, Percentage.ToString());
System.Threading.Thread.Sleep(100);
isNewFile = false;
}
}
catch (Exception objException)
{
throw objException;
}
finally
{
if (stream != null)
{
stream.Close();
stream.Dispose();
}
if (fs != null)
{
fs.Close();
fs.Dispose();
}
}
#endregion
}
In the above method, based on the size of the file, I have written logic to decide the buffer size of the stream, but it is entirely up to the developer how he wants to set the buffer size (byte array size) for reading the input stream. This article mainly concentrates on how to create/update the progress while the file download is in progress. In the above code, inside the while
loop, every time the total downloaded size is calculated, and the percentage of the download will be determined by the formula: total downloaded size / total file size * 100. Using the method setProgressBar(id, Percentage)
, we can set the progress for a particular progress bar with id
as id
. Below is the code for the SetProgressBar
method:
public static void setProgressBar(int id, string progressAmount)
{
StringBuilder sb = new StringBuilder();
sb.Append("<body><script type='text/javascript'>" +
"SetProgressBarProgressAmount(" + id + ",'" + progressAmount +
"'); </script></body>");
HttpContext.Current.Response.Write(sb.ToString());
HttpContext.Current.Response.Flush();
}
Search the web.config file for the entry FileStoreLocation
under appsettings
, and set it to the local folder location on your machine; files uploaded through the file upload control will be downloaded to this location.
Disclaimer
This article gives a starting point to users who want to have a similar kind of progress bar. This control is not ready for production deployment. This progress bar control does not take many things into consideration like file types that can be uploaded to the server etc. It is entirely the responsibility of the developer to make sure it fits to his requirements. I am not responsible for any kind of damage that this control causes to the application/product into which this product is being integrated. I expect the developer to evaluate the solution completely before integrating/using with existing applications.