When monitoring XHR file upload progress in Safari 9.1 (Chrome and Firefox do fine) using jQuery $.ajax()
, loaded
starts from 0 and total
from the file size. However, in some cases, when the upload finishes, total
suddenly doubles and loaded
continues incrementing. This makes the progress bar going from 0% to 100% and then back to 50% and finishing in 100%.
Files are correctly sent to the backend. The only problem is the progress bar, and the fact that the file is probably uploaded twice (I haven’t tested that).
I’ve tried clearing the input file element with $(e).val(“”)
, wrapping a form element and resetting it, and deleting it and creating a new one. Nothing works.
Also checked the FormData creation, used $.ajaxSettings.xhr()
to recover the XMLHttpRequest
, and new XMLHttpRequest()
to create it instead. Nothing changes.
Also tried jQuery 2.2.3 (instead of 1.11.3) and the behaviour is the same.
I’ve looked for similar code and couldn’t find any main difference and also couldn’t find any similar documented error except this one: Safari xhr drag'n'drop file upload seems to occur twice, where the guy solved the problem using a FormData object (which I am already using).
This is the relevant uploading code triggered on file input change:
function activityUploadImages(o){
var p, i, f, q, d;
p = $(o);
for(i = 0; f = o.files[i]; i++){
(q = $("<div>")).insertBefore(p)
.append($("<div>")
.append($("<span>"))
);
d = new FormData();
d.append("action", "uploadimage");
d.append("image", f);
ldAjax(
"POST",
"",
d,
{
context: q,
onProgress: function(p, t, q){
q.find("span").animate({
"height": p / t * 100 + "%"
}, {
queue: false,
duration: 200
});
}
}
);
}
p.val("");
}
function ldAjax(type, url, data, options){
var o;
o = {
type: type,
url: url,
data: data
};
if(options.onProgress)
o.xhr = function(){
var x;
x = $.ajaxSettings.xhr();
x.upload.onprogress = function(e){
options.onProgress(e.loaded, e.total, options.context);
};
return x;
}
if(data instanceof FormData){
o.contentType = false;
o.processData = false;
}
return $.ajax(o);
}