Displaying File Upload Progress using jQuery UI Progressbar Widget
While uploading large files you may need to display the progress of the file
upload operation to the end user. This can be done using HTML5 and jQuery UI's
Progressbar widget. While HTML5 also has <progress> element that can be used to
render a progress bar, jQuery UI's Progressbar widget offers more configuration
and theming options. In this post you will use XMLHttpRequest (Level 2) object
to upload files to the server. The XMLHttpRequest object now supports file
upload related events such as progress that can be used to track file upload
progress.
The following figure shows a sample Web Form that shows how the progress bar
looks like:
The Web Form has a FileUpload server control that allows you to select one or
more files. Clicking on the Upload button uploads the files on the server. To
upload the files on the server you use XMLHttpRequest object instead of
traditional postback. The files are uploaded in the background and the progress
of the upload operation is displayed in the Progressbar widget. The progress bar
also has a label that indicates the progress in percentages.
The Web Form consists of the following markup:
<form id="form1" runat="server">
<asp:Label ID="Label1" runat="server" Text="Select File(s) to Upload :"></asp:Label>
<br />
<br />
<asp:FileUpload ID="FileUpload1" runat="server" AllowMultiple="true" />
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Upload" />
<br />
<br />
<div id="progressbar" class="progressbar">
<div id="progresslabel" class="progressbarlabel"></div>
</div>
</form>
As you can see the form primarily consists of a FileUpload server control, a
Button and couple of <div> elements at the bottom. The outer <div> represents
the Progressbar whereas the inner <div> represents the label of the progress
bar.
Then add the following CSS classes for the outer <div> and the inner <div>
respectively.
.progressbar {
width:300px;
height:21px;
}
.progressbarlabel {
width:300px;
height:21px;
position:absolute;
text-align:center;
font-size:small;
}
Now add the <script> sections to the head section as shown below:
<script src="Scripts/jquery-2.0.0.js"></script>
<script src="Scripts/jquery-ui.js"></script>
As you can see the first <script> tag points to the jQuery library and the
second <script> tag points to the jQuery UI library. Also add a reference to the
CSS file needed by jQuery UI:
<link href="jquery-ui.css" rel="stylesheet" />
Then add a new <script> block in the head section and write the following
jQuery code in it:
$(document).ready(function () {
$("#Button1").click(function (evt) {
var xhr = new XMLHttpRequest();
var data = new FormData();
var files = $("#FileUpload1").get(0).files;
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
}
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var progress = Math.round(evt.loaded * 100 / evt.total);
$("#progressbar").progressbar("value", progress);
}
}, false);
xhr.open("POST", "UploadHandler.ashx");
xhr.send(data);
$("#progressbar").progressbar({
max: 100,
change: function (evt, ui) {
$("#progresslabel").text($("#progressbar").progressbar("value") + "%");
},
complete: function (evt, ui) {
$("#progresslabel").text("File upload successful!");
}
});
evt.preventDefault();
});
});
The above code consists of click event handler of Button1. Inside, the code
creates an instance of XMLHttpRequest object (xhr) and a FormData object (data).
It then obtains a list of files selected in the FileUpload control using files
property of the DOM element. A for loop iterates through the files collection
and with each iteration the file is added to the FormData object using its
append() method. The first parameter of append() is the name of the file and the
second parameter is the file itself.
Then progress event handler is wired to the upload object of the
XMLHttpRequest object. This event is raised periodically during the file upload
operation. The progress event handler uses event object properties such as
lengthComputable, loaded and total to calculate the progress in percentages. The
jQuery UI Progressbar is updated with this progress value. This is done by
setting the value option of the progressbar widget to the progress value just
calculated.
Then the open() method of XMLHttpRequest is called and the URL to an ASP.NET
generic handler (UploadHandler.ashx) is specified. Then send() method is called
to actually make the request and send the files to the server. The FormData
object is passed as a parameter to the send() method.
Finally, the Progressbar widget is initialized on the progressbar <div>
element. The configuration options namely max, change and complete are passed to
the progressbar widget. The max option indicates the maximum value that can be
displayed in the progress bar. the change options wires an event handler to the
change event of the progressbar widget. The change event is raised whenever the
value of the progressbar widget changes. The change event handler sets the text
of the progressbarlabel <div> element to the value of the progressbar. The
complete options wires an event handler for the complete event. The complete
event is raised when the value reaches the max value of the progressbar widget.
The complete event handler sets the text of the progressbarlabel <div> to "File
upload successfully!".
Although not used in this example, you can also handle the load event of the
XMLHttpRequest object to notify the user of the completion of the request.
Now add a generic handler (UploadHandler.ashx) to the project and add the
following code to it:
public void ProcessRequest(HttpContext context)
{
HttpFileCollection files = context.Request.Files;
foreach (string key in files)
{
HttpPostedFile file = files[key];
string fileName = file.FileName;
fileName = context.Server.MapPath("~/uploads/" + fileName);
file.SaveAs(fileName);
}
context.Response.ContentType = "text/plain";
context.Response.Write("File(s) uploaded successfully!");
}
The generic handler receives the uploaded files in the Request.Files
collection. Each file in the collection is an instance of HttpPostedFile class.
A foreach loop iterates through the files collection and saves each PostedFile
using the SaveAs() method. The files are saved in Uploads folder under the root
folder of the web application. Once all the files are uploaded the generic
handler sends a success message to the client.
That's it! Run the Web Form, select a few large files and click on the Upload
button to see the progressbar widget in action.