I'm using jQuery to upload a photo, and have attached a listener for onprogress events. However even when uploading photos that are a few megabytes, the only onprogress event that gets fired is when its at 100%. I've seen other sites like dropbox and facebook show a much more fluid progress bar. How can I get more frequent updates on the upload progress?
Sample upload Code:
var file = $photoFile.get(0).files[0];
var fileBlob = file && file.slice();
var formData = new FormData();
var title = $photoTitle.val();
formData.append('file', fileBlob);
formData.append('title', title);
$.ajax({
url: '/api/v1/photo/submit',
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
xhrFields: {
onprogress: function(ev) {
console.info('upload progress', ev);
if (ev.lengthComputable) {
var percentUploaded = Math.floor(ev.loaded * 100 / ev.total);
console.info('Uploaded '+percentUploaded+'%');
// update UI to reflect percentUploaded
} else {
console.info('Uploaded '+ev.loaded+' bytes');
// update UI to reflect bytes uploaded
}
}
}
}).done(function(response) {
// do stuff
}).fail(function() {
// handle error
});
I was able to do this borrowing code from this stackoverflow question.
The key mistake I was making was relying on the onprogress
within the xhrFields
property of the call to $.ajax
. Instead, to get more frequent progress updates I passed a custom XMLHttpRequest using the xhr
property:
$.ajax({
url: '/api/v1/photo/submit',
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener('progress',function(ev) {
if (ev.lengthComputable) {
var percentUploaded = Math.floor(ev.loaded * 100 / ev.total);
console.info('Uploaded '+percentUploaded+'%');
// update UI to reflect percentUploaded
} else {
console.info('Uploaded '+ev.loaded+' bytes');
// update UI to reflect bytes uploaded
}
}, false);
}
return myXhr;
}
}).done(function(response) {
// do stuff
}).fail(function() {
// handle error
});
Warning: This leverages newer web technologies and doesn't work with older browsers, especially IE.