XMLHttpRequest Level 2 – Déterminé si le téléchargement est terminé

J'utilise ajax pour les téléchargements de fichiers. Une fois le fichier téléchargé, php devrait le vérifier (mime, taille, virus (clamscan) et plus) – cela prend quelques secondes pour les fichiers plus importants. Alors que le fichier est en cours de chargement, un HTML5 <progress> se remplit, lorsque le fichier est prêt et PHP commence à vérifier, la progression devrait passer à une durée indéterminée. J'ai pensé à des façons de le faire (ce qui ne fonctionne pas tous les deux):

Vérification de l'événement upload.onload

 xhr.upload.addEventListener("load", function (e) { $("#uploadprogress").attr("value", false); $("#uploadprogress").attr("max", false); $("#progress").text("Checking file..."); }); 

Cela ne fonctionne pas, car le déclencheur-on-feu se déclenche lorsque la demande est prête, et non lorsque le téléchargement est prêt.

Vérification du pourcentage de progression du téléchargement = 100%

 xhr.upload.addEventListener("progress", function (e) { if (e.lengthComputable && e) { p = (e.loaded / e.total); if (p==1) { $("#uploadprogress").attr("value", false); $("#uploadprogress").attr("max", false); $("#progress").text("Checking file..."); } else { var percent = Math.ceil(p * 1000) / 10; $("#uploadprogress").val(e.loaded); $("#uploadprogress").attr("max", e.total); $("#progress").text("Uploading... " + percent + "%"); } } } }); 

Cela ne fonctionne pas, car le pourcentage de chargement s'arrête parfois à env. 97%, même si le téléchargement est terminé et que PHP commence à gérer les fichiers

Existe-t-il une autre possibilité de vérifier cela?

L'événement que vous souhaitez écouter est readystatechange sur l'objet XHR (pas sur XHR.upload). readyState est 4 lorsque le téléchargement a terminé l'envoi et que le serveur ferme la connexion . loadend / load fire lorsque le téléchargement est terminé indépendamment du fait que le serveur ferme la connexion. Juste pour référence, voici les événements que vous pouvez écouter et quand ils tirent:

  var xhr = new XMLHttpRequest(); // ... // do stuff with xhr // ... xhr.upload.addEventListener('loadstart', function(e) { // When the request starts. }); xhr.upload.addEventListener('progress', function(e) { // While sending and loading data. }); xhr.upload.addEventListener('load', function(e) { // When the request has *successfully* completed. // Even if the server hasn't responded that it finished. }); xhr.upload.addEventListener('loadend', function(e) { // When the request has completed (either in success or failure). // Just like 'load', even if the server hasn't // responded that it finished processing the request. }); xhr.upload.addEventListener('error', function(e) { // When the request has failed. }); xhr.upload.addEventListener('abort', function(e) { // When the request has been aborted. // For instance, by invoking the abort() method. }); xhr.upload.addEventListener('timeout', function(e) { // When the author specified timeout has passed // before the request could complete. }); // notice that the event handler is on xhr and not xhr.upload xhr.addEventListener('readystatechange', function(e) { if( this.readyState === 4 ) { // the transfer has completed and the server closed the connection. } }); 

Basé sur https://bugzilla.mozilla.org/show_bug.cgi?id=637002 .

Allons chercher un exemple de travail complet …

 // YOUR (SIMPLE) JAVASCRIPT FILE var form = new FormData(), xhr = new XMLHttpRequest(); form.append('inputname', YOURFILE); xhr.open('POST', 'http://oneserver/onephpfile', true); xhr.setRequestHeader('X-CSRF-Token', 'somestring'); xhr.onreadystatechange = function () { if ((xhr.readyState === 4) && (xhr.status === 200)) // do other thing with xhr.responseText.trim() }; xhr.upload.addEventListener('loadstart', showProgressBarFunction, false); xhr.upload.addEventListener('progress', updateProgressBarFunction, false); xhr.upload.addEventListener('load', updateProgressBarFunction, false); xhr.send(form); // YOUR FIRST (SIMPLE) PHP FILE header('Content-Type: text/plain; charset=utf-8'); header('Cache-Control: no-cache, must-revalidate'); sleep(20); echo 'file processing ended'; 

Avec ce premier fichier PHP, vous verrez: 10% … 50% … 75% … 'faire autre chose' avec Firefox (4/10/28/32) et IE (10/11). Cependant, vous verrez: 10% … 50% … 75% … 100% … 'faire autre chose' avec Chrome / Chromium (33/37) et Opera (24).

 // YOUR SECOND (SIMPLE) PHP FILE header('Content-Encoding: chunked', true); header('Content-Type: text/plain; charset=utf-8'); header('Cache-Control: no-cache, must-revalidate'); ini_set('output_buffering', false); ini_set('implicit_flush', true); ob_implicit_flush(true); for ($i = 0; $i < ob_get_level(); $i++) ob_end_clean(); echo ' '; sleep(20); echo 'file processing ended'; 

Avec ce deuxième fichier PHP, vous verrez: 10% … 50% … 75% … 100% … 'faire autre chose' avec Chrome / Chromium (33/37/53), Opera (24 / 42), Firefox (4/10/28/32/45), IE (10/11) et Edge (14)!

Il s'agit d'une chute relativement connue de la spécification hTML5, lorsqu'ils pourraient facilement l'étendre pour ajouter des informations telles que timeRemaining et transferSpeed.

Avez-vous envisagé d'utiliser math.round plutôt que de math.ceil pour var percent sorte que vous faites de la biscuit dans un peu de flou qui aiderait à contourner quelques points de pourcentage?

Vous devez également ajouter un autre auditeur pour loadComplete, si vous obtenez l'interface utilisateur bloquée à <100% même si elle est terminée sur le backend:

 //only fires once xhr.addEventListener('loadend', uploadComplete, false); function uploadComplete(event) { console.log('rejoice...for I have completed'); //do stuff } 

Vérifiez l'état prêt, if(readyState==4) {//it has finished, put code here}