Reputation: 4698
I am trying to make a progress bar for my jQuery/AJAX upload script. Everything in the script works fine, except the progress bar's value never changes. Also, in console, the percentComplete variable is always just 1 and it logs twice. I've tried every different thing I can find, but nothing seems to work. The progress bar itself is added to my div, but that's about it.
$.ajax({
beforeSend : function(){
$(settings.message_div).html('<progress id="#upload-progress" value="0" max="100"></progress>');
},
xhr: function()
{
var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with upload progress
console.log(percentComplete);
$('#upload-progress').val(percentComplete);
}
}, false);
//Download progress
xhr.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with download progress
console.log(percentComplete);
$('#upload-progress').val(percentComplete);
}
}, false);
return xhr;
},
type: "POST",
dataType: "xml",
data: formData,
url: settings.ajax_url,
processData: false,
contentType: false,
cache: false,
success: function(xml){
//console.log('ajax called');
},
error: function(xhr){
$(settings.message_div).html(xhr.responseText);
//console.log(xhr.responseText);
}
});
This was taken from here
Upvotes: 1
Views: 2924
Reputation: 589
onprogress
should work recently. The tutorial you have seen is a little bit outdated.
http://www.html5rocks.com/en/tutorials/file/xhr2/
http://www.w3.org/TR/progress-events/#introduction
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var progressBar = $('#upload-progress').get(0);
progressBar.value = (e.loaded / e.total) * 100;
progressBar.textContent = progressBar.value; // Fallback for unsupported browsers.
}
Upvotes: 1
Reputation: 4847
The tutorial you've followed is really old and was probably relevant around Jquery 1.5. But as of that version, the old XHR
object has been hidden and is replaced by the JQXhr object with a higher level of abstraction:
The jQuery XMLHttpRequest (jqXHR) object returned by $.ajax() as of jQuery 1.5 is a superset of the browser's native XMLHttpRequest object. For example, it contains responseText and responseXML properties, as well as a getResponseHeader() method. When the transport mechanism is something other than XMLHttpRequest (for example, a script tag for a JSONP request) the jqXHR object simulates native XHR functionality where possible.
The attributes for this object are not very well documented and I am not sure if it still supports upload
and progress
functionality like you try to exploit in your code.
Even in the comments of that blog, people suggested using the onprogress
attribute in the xhrFields
option but again this SO Post confirms that it's not possible in the newer versions of Jquery as it has been deprecated. In that post only, the answer suggests :
The xhr option parameter must be a function that returns a native XmlHttpRequest object for jQuery to use.
Code snippet from the answer:
$.ajax({
async: true,
contentType: file.type,
data: file,
dataType: 'xml',
processData: false,
success: function(xml){
// Do stuff with the returned xml
},
type: 'post',
url: '/fileuploader/' + file.name,
xhr: function(){
// get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr() ;
// set the onprogress event handler
xhr.upload.onprogress = function(evt){ console.log('progress', evt.loaded/evt.total*100) } ;
// set the onload event handler
xhr.upload.onload = function(){ console.log('DONE!') } ;
// return the customized object
return xhr ;
} ;
});
Another relevant Answer on similar lines where he uses a deferred object's progress
attribute and defines the upload progress event handlers inside it.
TLDR- It is not established if you can use the native XHR
object and exploit it's upload and progress events like you mention in the latest versions of Jquery.
You should probably look at the code for some HTML5 and jquery file upload plugins. I was just going through one on github and I'm just copy-pasting some code from fileupload.js
in the project:
_onProgress: function (e, data) {
if (e.lengthComputable) {
var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
loaded;
if (data._time && data.progressInterval &&
(now - data._time < data.progressInterval) &&
e.loaded !== e.total) {
return;
}
data._time = now;
loaded = Math.floor(
e.loaded / e.total * (data.chunkSize || data._progress.total)
) + (data.uploadedBytes || 0);
// Add the difference from the previously loaded state
// to the global loaded counter:
this._progress.loaded += (loaded - data._progress.loaded);
this._progress.bitrate = this._bitrateTimer.getBitrate(
now,
this._progress.loaded,
data.bitrateInterval
);
data._progress.loaded = data.loaded = loaded;
data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
now,
loaded,
data.bitrateInterval
);
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
this._trigger(
'progress',
$.Event('progress', {delegatedEvent: e}),
data
);
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
this._trigger(
'progressall',
$.Event('progressall', {delegatedEvent: e}),
this._progress
);
}
},
_initProgressListener: function (options) {
var that = this,
xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
// Accesss to the native XHR object is required to add event listeners
// for the upload progress event:
if (xhr.upload) {
$(xhr.upload).bind('progress', function (e) {
var oe = e.originalEvent;
// Make sure the progress event properties get copied over:
e.lengthComputable = oe.lengthComputable;
e.loaded = oe.loaded;
e.total = oe.total;
that._onProgress(e, options);
});
options.xhr = function () {
return xhr;
};
}
}
This definitely works as the project is very well maintained and has working demos. I think it should be a good starting point for you. Hope it helps.
Upvotes: 0