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}