13

I'm trying to create a progress bar for a file upload, but for some reason, the XHR progress response is only firing once, at the end. However it works 100% fine (fires throughout the file upload) if I have the firebug window open. I'm testing this on localhost.

My code is really long but here's the gist of it:

is_uploading = $.ajax({
  url: "/includes/upload.php?a=" + a_id,
  type: "POST",
  data: formdata,
  processData: false,
  contentType: false,
  dataType: "JSON",
  xhr: function () {
    var xhr = new window.XMLHttpRequest();
    xhr.upload.addEventListener("progress", function (evt) {
      alert('yay');//test to see if the event is firing...this should be alerting A LOT
      if (evt.lengthComputable) {
        //do stuff
      }
    }, false);

    return xhr;
  }

  ...more options here beforesend, success, etc

I've been pulling my hair out for the past few hours over this, so any help would be appreciated. I have no idea why it works with the firebug console open, but only fires at the end if it's closed...

n1stre
  • 5,856
  • 4
  • 20
  • 41
Will S.
  • 131
  • 1
  • 5
  • Generally you'd also add a `xhr.addEventListener("progress" ...` handler, did you look at some of the many examples online ? – adeneo Feb 19 '15 at 19:59
  • Yes, I have look at the many examples online. As I'm sure you already know, xhr.addEventListener would be used to monitor downloading events. I'm only interested in uploading. – Will S. Feb 19 '15 at 20:11
  • As per the latest support mentioned [here](https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress), try registering event handler on `xhr` instead of `xhr.upload` – Arkantos Feb 19 '15 at 20:15
  • I've tried registering it on the xhr to no avail. From the support docs that you linked: "Progress events exist for both download and upload transfers. The download events are fired on the XMLHttpRequest object itself, as shown in the above sample. The upload events are fired on the XMLHttpRequest.upload object, as shown below" – Will S. Feb 19 '15 at 20:18
  • Why would the dataType be `JSON` ? – adeneo Feb 19 '15 at 20:19
  • are you doing anything in beforeSend ? It would help if you can add your full ajax definition – Arkantos Feb 19 '15 at 20:22
  • According to http://api.jquery.com/jquery.ajax/, the available types are xml,html,script,json,jsonp, or text. Removing this field makes jQuery do an "Intelligent Guess" on the data (I've tested deleting the field and it doesn't make a difference). I feel like there's some weird race condition going on, since it works with the firebug console open... – Will S. Feb 19 '15 at 20:24
  • the beforeSend is just one line of code that makes a separate loading gif visible...the only other field I've defined, but not shown, is success, so that shouldn't make a difference to the progress – Will S. Feb 19 '15 at 20:26
  • I think your looking for .addEventListener('readystatechange', function(){}) – Camway Feb 19 '15 at 22:25

1 Answers1

3

This could be to do with the size of the file being uploaded and/or your upload speed.

If you are uploading something that's relatively small the upload will complete "instantly", not giving the progress event time to fire during the upload, but instead only firing once on completion:

From https://stackoverflow.com/a/5543745/11743318:

While the request entity body is being uploaded and the upload complete flag is false, queue a task to fire a progress event named progress at the XMLHttpRequestUpload object about every 50ms or for every byte transmitted, whichever is least frequent. - W3 XMLHttpRequest Level 2


I've throttled my network to GPRS to illustrate this point here:

One progress event

Multiple progress events

One can see from the images that without throttling the upload happens so quickly that the progress event is only fired once on completion. The progress bar has a transition applied to its width so it doesn't jump to 100% but rather fills smoothly.

However, in the lower image, when throttled to GPRS, one can see that 36 events are fired in total. The browser-specific implementation mentioned in the linked answer is evident here with the event firing for every 2560 bits = 320 bytes transmitted.

compuphys
  • 1,289
  • 12
  • 28