====== Html5 File Upload with Progress ====== Posted by Shiv Kumar on 25th September, 2010\\ Categorized Under: Html 5 File Upload\\ Tagged With: File API File Upload XMLHttpRequest\\ http://www.matlus.com/html5-file-upload-with-progress/ Html5 finally solves an age old problem of being able to upload files while also showing the upload progress. Today most websites use Flash Player to achieve this functionality. Some websites continue to use the Html **
var fd = new FormData();
fd.append("author", "Shiv Kumar");
fd.append("name", "Html 5 File API/FormData");
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
**Code Listing 4: Manually creating a FormData instance**\\
Going back to Code Listing 3, you'll notice we've subscribed to a few events of the XMLHttpRequest object. In particular, pay attention to the first line after the event listners comment in the code.\\ **xhr.upload.addEventListener("progress", uploadProgress, false);** The progress event we subscribe to is not that of the XMLHttpRequest instance, but rather the **upload** property of the XMLHttpRequest instance, which is an [[https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#xmlhttprequestupload|XMLHttpRequestUpload]] type that is really an event target that has a **progress** event we can subscribe to in order to get progress information on the upload that is taking place. We don't have to worry about this object. Just remember, when using XMLHttpRequest for uploading data to the server, you must subscribe to its **upload** property's **progress** event.
=== A note about Progress Events ===
The XMLHttpRequest object does have a progress event of it's own and you'll subscribe to that event when you download data from the server (which we are not covering here).
=== The Event handler implementations ===
function uploadProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
function uploadComplete(evt) {
/* This event is raised when the server send back a response */
alert(evt.target.responseText);
}
function uploadFailed(evt) {
alert("There was an error attempting to upload the file.");
}
function uploadCanceled(evt) {
alert("The upload has been canceled by the user or the browser dropped the connection.");
}
**Code Listing 5: The implementation of the various event handlers**\\
The code listing above is pretty self explanatory so there is nothing much to say here.
===== The Minimalistic Solution =====
The Code listing below is the entire Html page including the JavaScript and Html required to get a bear minimum File upload with progress indicator working. I've intentionally kept it simple so if you want to do your own layout and information display you can start with this and expand it. Html5 also introduces a progress element that can be used to show **progress**. The progress element has **max** and **value** and so it makes it really simple to show progress. However, at the time of this writing, only Chrome 6 supports this element so I've not used it in the minimalistic solution.
==== Change the Url to the server side script ====
Be sure to change the url to point to the url of your server side script that handles file uploads. In the code listing below, it is **UploadMinimal.aspx** in the **uploadFile()** method: **xhr.open("POST", "UploadMinimal.aspx");**
==== Minimalistic Html and JavaScript ====
Upload Files using XMLHttpRequest - Minimal
**Code Listing 6: The Complete but minimalistic code listing**\\
Well, that pretty much covers the minimalistic version of the new Html5 feature. Getting at the other information that you see in Figure2 is mathematical really. It is quite a bit of extra work to not only get at the information, but to display and animate etc. For instance to get the rate of upload (the upload speed). We do the following:
- in the **uploadProgress(evt)** event, should store the **evt.loaded** and **evt.total** in global variables.
- We set up a timer event to fire every second.
- In the timer callback we get the difference of the number of bytes transfered between now and the last time the callback was called (so 1 second ago).
- That gives us the number of bytes per second.
Which is the upload speed. Note that in the demo I set up the timer to fire every 500 milliseconds to get more granularity. As a result the difference between the number of bytes is doubled since the number of bytes is really the number of bytes transferred in half a second. I won't go into how to find the time remaining, but it's all there in the demo. Do a "view source" to see the code in the demo's html page. I hope you found this article helpful.