138 votes

Comment obtenir la progression à partir de XMLHttpRequest ?

Est-il possible d'obtenir la progression d'une XMLHttpRequest (octets chargés, octets téléchargés) ?

Cela peut être utile pour afficher une barre de progression lorsque l'utilisateur télécharge un fichier volumineux. L'API standard ne semble pas le supporter, mais peut-être existe-t-il une extension non standard dans l'un des navigateurs existants ? Cela semble être une fonctionnalité assez évidente à avoir après tout, puisque le client sait combien d'octets ont été chargés/téléchargés.

Le principal problème de cette solution (outre la complexité du code côté serveur) est qu'en général, lors du téléchargement d'un gros fichier, la connexion de l'utilisateur est complètement interrompue, car la plupart des fournisseurs d'accès à Internet offrent une mauvaise connexion en amont. Donc, faire des requêtes supplémentaires n'est pas aussi réactif que je l'avais espéré. J'espérais qu'il y aurait un moyen (peut-être non standard) d'obtenir cette information, que le navigateur possède à tout moment.

138voto

albanx Points 1370

Pour les octets téléchargés, c'est assez facile. Il suffit de surveiller le xhr.upload.onprogress Le navigateur connaît la taille des fichiers à télécharger et la taille des données téléchargées, ce qui lui permet de donner des informations sur la progression.

Pour les octets téléchargés (lorsque vous obtenez des informations avec la fonction xhr.responseText ), c'est un peu plus difficile, car le navigateur ne sait pas combien d'octets avec envoyer le processus du serveur. La seule chose que le navigateur connaît dans ce cas est la taille des octets qu'il reçoit. Mais il y a une solution pour cela, il suffit de mettre un en-tête 'Content-Length' sur le script du serveur afin de donner la taille des octets que le navigateur reçoit. pour plus d'informations, voir https://developer.mozilla.org/en/Using_XMLHttpRequest .

Exemple : Mon serveur script lit un fichier zip (cela prend 5 secondes) :

$filesize=filesize('test.zip');

header("Content-Length: ".$filesize);//set header length
//if the headers it not set then the evt.loaded will be 0
readfile('test.zip');
echo "asdasd";

Maintenant je peux surveiller le processus de téléchargement du script du serveur car je connais sa longueur totale :

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  //evt.loaded the bytes browser receive
      //evt.total the total bytes seted by the header
      //
     var percentComplete = (evt.loaded / evt.total)*100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress=updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  

            }  
    };  
    req.send(); 
}

10voto

Markus Peröbner Points 177

6voto

Sean McMains Points 9311

Il y a une discussion intéressante sur l'indicateur de progression pour le modèle AJAX ici :

http://ajaxpatterns.org/Progress_Indicator

L'une des approches les plus prometteuses semble être l'ouverture d'un second canal de communication vers le serveur pour lui demander quelle partie du transfert a été achevée.

5voto

4voto

Orclev Points 460

Pour le total téléchargé, il ne semble pas y avoir de moyen de le gérer, mais il y a quelque chose de similaire à ce que vous voulez pour le téléchargement. Une fois que readyState est à 3, vous pouvez périodiquement interroger responseText pour obtenir tout le contenu téléchargé jusqu'à présent sous forme de chaîne (cela ne fonctionne pas dans IE), jusqu'à ce que tout soit disponible, auquel cas il passera à readyState 4. Le nombre total d'octets téléchargés à un moment donné sera égal au nombre total d'octets de la chaîne stockée dans responseText.

Pour une approche tout ou rien à la question du téléchargement, puisque vous devez passer une chaîne pour le téléchargement (et qu'il est possible de déterminer le nombre total d'octets de cette chaîne), le nombre total d'octets envoyés pour les états readyState 0 et 1 sera de 0, et le total pour l'état readyState 2 sera le nombre total d'octets de la chaîne que vous avez passée. Le total des octets envoyés et reçus dans les états readyState 3 et 4 sera la somme des octets de la chaîne originale plus le total des octets de responseText.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X