I am trying to monitor the progress of my files upload, but the "progress" event is never fired on chrome, firefox and opera. It works perfectly on Safari however.
I use the package meteor-slingshot to manipulate my files. Here is the code that the package use in order to send the files :
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function (event) {
if (event.lengthComputable) {
loaded.set(event.loaded);
total.set(event.total);
}
}, false);
xhr.open("POST", self.instructions.upload, true);
_.each(self.instructions.headers, function (value, key) {
xhr.setRequestHeader(key, value);
});
xhr.send(buildFormData());
Do you have an idea of what is the problem? Is the problem coming directly from those browsers ?
Related
I will try to explain my problem very detailed.
NOTE-1: It is not an issue with small files or whatever. I'm testing it with large files, with slow upload speed network
throttling...etc
NOTE-2: The progress bar works perfectly in other browser (Tested in edge)
NOTE-3: This issue only occurs in CHROME browser
I'm currently working on a file Uploader by using XHR. Everything works good, files are upload ...etc
I made a progress bar which its working, but only the very first time. (Or when I do CTRL+SHIFT+R), which basically clears the cache. (I have even ticked clear cache in developer mode which is active during testing)
As I said, it works the very first time, however, when I refresh the page, the progress even is not fired. However, load event is fired (This event is only fired when the file is fully uploaded)
I tested the code and everything is working fine in Edge browser, I can refresh and progress event is fired correctly, however is not the same for Chrome.
I have read some articles about that content-length must exists in headers and be greater than zero, and it is.
This is my script (The upload part)
let uploadFile = () => {
//... Some other stuffs
console.log("Upload started")
let xhr = new XMLHttpRequest();
let formData = new FormData();
formData.append('file', file);
xhr.open("POST", "uploaderServerside.php");
xhr.upload.addEventListener('progress', function(evt){
console.log("Uploading: " + (Math.round(evt.loaded / evt.total * 100)) + "%");
}, false);
xhr.addEventListener("load", () => {
console.log("Upload finished")
});
xhr.send(formData);
}
I hope you can bring me a hand with this issue, thanks for reading and best regards.
Sound like chrome has some aggressive caching, you can check the network tab to see if the request is loaded from cache, you will see (disk cache) under the size column.
To avoid the cache you can use a cache buster
xhr.open("POST", "uploaderServerside.php?_="+(new Date()).getTime());
Or you can set Headers on uploaderServerside.php to force the browser to not cache the request like
Cache-Control: no-store
Expires: 0
I'm working on an uploader for angular-js that can give me progress updates. The code below works however on chrome, for files that are under around 3MB, one progress update fires before it starts sending, and the event data indicates that all the bytes are uploaded. It then takes some time (up to 30secs) before the file data is actually sent (and no further progress events will fire during the actual upload). If I use a larger file, I'll get two events or maybe three. On firefox, I'll get around 6 progress events for a 2MB file. Does anyone know if there's a way to adjust the granularity of these updates to fix this. To me, this function is basically useless (on chrome) since most documents aren't that big. Thanks.
send: function() {
var document = {
DocumentName: this.fsEntry.file.name
};
var formdata = new FormData();
formdata.append('file', this.fsEntry.file);
formdata.append('metadata', JSON.stringify(document));
this.xhr = new XMLHttpRequest();
this.xhr.addEventListener("loadstart", this.onLoadStart, false);
this.xhr.upload.addEventListener("progress", this.onProgress, false);
this.xhr.addEventListener("load", this.onComplete, false);
this.xhr.open("POST", this.fsEntry.uploadUri, true);
this.xhr.send(formdata);
}
this.onProgress = function(e) {
if (e.lengthComputable) {
console.log("progress: uploaded " + e.loaded + " of " + e.total);
}
}
I use AJAX upload for my site, and Javascript is the choice (not jQuery).
But What I have come up with does not work with Firefox. Here is the XMLHttpRequest code block:
var xhr = new XMLHttpRequest();
xhr.open("POST", "upload.php");
xhr.onprogress = function(event){
if(event.lengthComputable)
{
console.log(event.loaded);
}
};
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.send(formData);
And pay attention to xhr.onprogress event.
Alternatively, I also use the following code for progress:
xhr.upload.addEventListener("progress", function(){
// do something
}, false);
But:
For the first solution which is xhr.onprogress it has a problem:
It just shows the amount of event.loaded after the upload has been finished. This amount is the same as the file size since the upload has fully loaded the file.
It works in both FF and chrome, but I don;t want it to just throw a value after the progress has reached to its end.
The second solution, though, is nice and works OK, but it in no way works in firefox. In firefox however, no error is thrown, and as I have tested, the progressEvent does not get triggered at all.
Both chrome and Firefox are of latest versions.
I think problem is you add onprogress listener after open(), it should be done before:
var xhr = new XMLHttpRequest();
xhr.onprogress = function (event) {
if (event.lengthComputable) {
console.log(event.loaded);
}
};
xhr.open("POST", "upload.php");
Or:
var xhr = new XMLHttpRequest();
xhr.addEventListener("progress", function (event) {
if (event.lengthComputable) {
console.log(event.loaded);
}
}, false);
xhr.open("POST", "upload.php");
I have searched relentlessly but just can't figure this one out. Why will this XHR connection work perfectly fine in Firefox but breaks in Chrome? I'm using this in conjunction with AngularJS, by the way.
$scope.upload = function(project, file) {
var formData = new FormData(); //Not really sure why we have to use FormData(). Oh yeah, browsers suck.
formData.append('', file.file); //The real file object is stored in this file container
file.xhr = new XMLHttpRequest();
file.xhr.open('PUT', '/api/projects/'+project._id+'/files', true);
//Progress event listener
file.xhr.upload.onprogress = function(event) {
if(event.lengthComputable) {
file.uploadPercent = Math.round(event.loaded / event.total * 100);
}
};
//Upload complete listener
file.xhr.upload.onload = function(event) {
file.uploaded = true;
};
//Every time the status changes
file.xhr.onreadystatechange = function(event) {
if(event.target.readyState == 4) {
//The file has been added, so tag the ID onto the file object
console.log(event.target.responseText);
file._id = JSON.parse(event.target.responseText)._id;
} else {
return;
}
};
file.xhr.send(formData);
};
In Firefox, the file is sent just fine to my server, and the responseText is returned exactly like I'd expect. However, in Chrome, I get this error: Error: INVALID_STATE_ERR: DOM Exception 11
Error: An attempt was made to use an object that is not, or is no longer, usable., which would be more helpful if it told me exactly what object was attempted to be used. I've read here that I should try to set async to false and use onreadystatechange, but I'm not sure how that helps, since I'm already using onreadystatechange.
Bug from 2009: XMLHttpRequest doesn't work while submitting a form - https://bugs.webkit.org/show_bug.cgi?id=23933
Im working on bookmarklets and my issue is js not getting update
I load js file with my bookmarklet, And my problem is its not getting update with my latest version. even also if i have updated it in my database.
So what i want it to check and load latest version when ever bookmark is clicked. so i want to know if there something to add in js file so it get load latest version. Or if there is way to check date and time or check version. etc
I have no problem with codes as they working fine.
Suppose this is my js
function start() {
// codes
};
// ---------------------------------------
// Ajax
// ---------------------------------------
function AJAXInteraction(url, callback) {
var req = init();
req.onreadystatechange = processRequest;
function init() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
function processRequest() {
if (req.readyState == 4) {
if (req.status == 200) {
if (callback) callback(req.responseText);
}
}
}
this.doGet = function () {
req.open("GET", url, true);
req.send(null);
}
this.doPost = function (str) {
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
req.send(str);
}
};
If you are appending a JS file to the page and you want to force your browser to always get a fresh copy of the file and not use the cache, then you can append any random text as part of the query string. Here is example code.
document.body.appendChild(document.createElement('script')).src = 'http://server.com/script.js?ts=' + new Date().getTime();
Alternatively, the server from which the file is being loaded could specify certain expiration information. To ensure you always get the latest, you could specify an expiration of sometime in the past.
Take a look at this: Setup HTTP expires headers using PHP and Apache