IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AJAX Discussion :

XHR upload : comment récupérer le vrai progress du upload ?


Sujet :

AJAX

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 155
    Points : 75
    Points
    75
    Par défaut XHR upload : comment récupérer le vrai progress du upload ?
    Bonjour à tous

    J'ai un processus de conversion de fichiers lancé par un script PHP qui récupère des fichiers uploadés PUIS les convertit, et renvoie à la fin les urls...

    Maintenant je voudrais afficher une jauge qui indique le progress du upload PUIS la conversion en cours (en bricolant un "indeterminate state") mais il semble que les handlers de la xhr ne permettent pas de récupérer des signaux corrects.

    Voilà ce que j'obtiens dans FF avec un fichier de plusieurs Mo :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    upload.progress 0.41712747074468304
    upload.progress 0.8961230685514022
    upload.progress 0.9965576293818433              // la conversion a l'air de démarrer ici : j'attends ... et le reste arrive tout d'un coup ..
    upload.progress 1
    upload.load (une chaîne vide)                         // inutile, arrive trop tôt ?
    progress 1
    load (> REPONSE)
    Ceci avec les déclenchements suivants :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    xhr.addEventListener('load', function(e) {
    	console.log('load', xhr.responseText);
    }, false);
    xhr.addEventListener('progress', function(e) {
    	console.log('progress', e.loaded / e.total);
    }, false);
     
    xhr.upload.addEventListener('load', function(e) {
    	console.log('upload.load', xhr.responseText);
    }, false);
    xhr.upload.addEventListener('progress', function(e) {
    	console.log('upload.progress', e.loaded / e.total);
    }, false);

    Je voudrais donc récupérer le signal de fin du upload indépendamment de celui de la requête globale, y a t-il un moyen qui fonctionne évidemment dans tous les navigateurs ?

    Merci par avance

  2. #2
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 382
    Points : 10 410
    Points
    10 410
    Par défaut
    Salut,

    Si une solution existe, je ne crois pas que ce soit à partir de l'écoute des événements retournés par xhr.addEventListener car par exemple 'loadend' est envoyé en tant voulu par Chrome (dès l'envoi de la requête complète) alors que IE et Firefox attendent le retour serveur. Pareil pour 'load'. Les navigateurs ne retournent malheureusement pas tous ces événements au même moment

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 155
    Points : 75
    Points
    75
    Par défaut
    Merci, oui ça dépend beaucoup des navigateurs et c'est donc une mauvaise nouvelle a priori...
    En attendant je teste un truc très simple qui m'a l'air de convenir (pour le moment ?) :

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    xhr.upload.addEventListener('progress', function(e) {
    	var ratio = e.loaded / e.total;
    	if( ratio > 0.99 )
    		onProgressEnded(); // peut être déclenché 2 fois
    	else
    		onProgress(ratio);
     
    }, false);

    Sinon la solution la plus fiable serait de faire 2 requêtes successives au lieu d'1 ?

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Par exemple.

    En principe la solution est de faire en sorte que le serveur réponde tout de suite à la fin de l'envoi, au lieu d'attendre d'avoir fini les traitements.
    Pas forcément d'envoyer la réponse entière, mais au moins les headers, le truc qui dit "j'ai bien reçu et compris la requête, et maintenant je t'envoie la réponse, que tu vas télécharger et dont la progression du téléchargement se mesurera à son tour."
    Le problème c'est que pour savoir si on doit répondre que tout va bien ou que ça ne va pas, il faut déjà savoir si tout va bien se passer, et donc il faut avoir terminé les traitements, et donc on ne peut pas répondre tout de suite. Ce n'est donc pas faisable avec XHR à moins que les navigateurs se mettent d'accord pour notifier la completion de l'upload avant de recevoir les headers..

    Une requête pour dire ce qu'il y a à faire et une requête pour demander comment ça s'est passé, est une manière de faire.

    Une autre serait de simuler une réponse streamée qui envoie des informations au fur et à mesure qu'elles sont disponibles. Ce qui veut dire qu'on envoie un début de réponse tout de suite et on envoie plus tard si ça s'est bien passé, ce qui est arrivé etc, avec possiblement un état d'avancement entre les deux. Mais il faut utiliser une technologie côté serveur qui est capable de ça. Les deux requêtes séparées est une solution plus simple.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 382
    Points : 10 410
    Points
    10 410
    Par défaut
    Citation Envoyé par krunch Voir le message
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    xhr.upload.addEventListener('progress', function(e) {
    	var ratio = e.loaded / e.total;
    	if( ratio > 0.99 )
    		onProgressEnded(); // peut être déclenché 2 fois
    	else
    		onProgress(ratio);
     
    }, false);
    Cela ne peut pas être fiable car le rafraîchissement du onprogress ne se fait pas en continu, mais à une fréquence qui doit en plus varier suivant les navigateurs (et possiblement suivant la puissance du périphérique ?). Bref tu risques de ne jamais rentrer dans ta condition "if(ratio > 0.99)" avant la réponse du serveur avec IE et FF.

    Et pour les deux requêtes séparées, cette fois-ci c'est Chrome qui pose problème avec un bug vieux comme Herod qui me semble-t-il va rentrer en conflit avec cette solution.

    Eventuellement tu pourrais essayer de faire un écouteur indépendant du onprogress (un bête setTimeOut avec un délai d'une seconde par exemple) pour scruter le résultat "loaded" du onprogress qu'il faudra enregistrer dans une variable indépendante. S'il ne progresse plus durant plus de x secondes tu peux considérer que tu es côté serveur. Faudra scruter en même temps l'état du timeout du xhr pour faire la différence avec une requête perdue.

    C'est du bricolage mais je vois pas d'autre solution avec xhr.upload et php côté serveur. Tu es tombé sur un des rares problèmes qui semble assez simple au départ mais qui finalement se transforme en un vrai casse-tête

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 155
    Points : 75
    Points
    75
    Par défaut
    Merci thelvin pour ces explication dont il ressort que c'est pas prévu pour en fait ... Ceci malgré que la distinction xhr / xhr.upload pourrait le laisser croire

    Donc dans l'idéal (en restant avec mes xhr) il faudrait des requêtes séparées qui suivent la 1ère (1 par fichier à traiter), ce qui permet effectivement de récupérer les résultats au fur et à mesure et de faire comme un flux .. Sauf que les requêtes seraient dans une boucle, et là le bug de chrome fait que tout s'effondre ! (il est effectivement très chiant, du moins si on ne peut pas mettre de xhr dans une boucle)

    Donc à voir ce problème.. (peut être les appeler l'une après l'autre avec Chrome et non pas en boucle ?) Sinon oui, un 'écouteur' mais ça risque d'être un sac de problèmes..
    ---------------------
    Bref tu risques de ne jamais rentrer dans ta condition "if(ratio > 0.99)" avant la réponse du serveur avec IE et FF.
    Apparemment ça finit toujours par un déclenchement onProgress avec ratio=1. Par contre ce bricolage est effectivement très très approximatif, il marche à peu près pour des gros fichiers avec FF et IE, et sinon il est déclenché juste avant le onLoad.

    Pas facile en effet, merci pour vos réponse.

  7. #7
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 382
    Points : 10 410
    Points
    10 410
    Par défaut
    Oui ça fini toujours par un ratio avec 1 mais avec FF ou IE le ratio 1 est obtenu après le retour du serveur. Et donc si tu fais des tests sur un serveur local ou pour des petits fichiers sur un serveur distant le rafraîchissement du onprogress ne sera pas suffisamment rapide pour rentrer dans la condition > 0.99 car au précédent refresh il sera peut-être à 0.85 et après plus rien avant le retour du serveur car le fichier sera déjà envoyé. Comprends-tu ce que je veux dire ?

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 155
    Points : 75
    Points
    75
    Par défaut
    Ce que je voulais dire c'est qu'au pire si il a raté le seuil il est toujours déclenché à la fin. D'autre part il sera plus facilement déclenché par les gros fichiers, ce qui tombe bien parce qu'avec les petits on n'a pas le temps de voir l'enchainement. Mais nous sommes d'accord c'est un bricolage pas fiable (avec Chrome ça marche rarement même avec des gros fichiers).

    Bon je verrai si je passe en multi-requête... si le bug de Chrome est surmontable... (peut être avec une récursive qui envoie les xhr en série plutôt qu'en parallèle ?)... vous dirai si je trouve un truc.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 155
    Points : 75
    Points
    75
    Par défaut
    Le bug de Chrome n'a pas l'air de poser de problème (il est juste question d'un submit button), il est possible de lancer les requêtes en boucle et donc de faire répondre à ce problème en séparant les requêtes... Merci pour vos réponses

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment récupérer le chemin du fichier uploadé
    Par keokaz dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 15/07/2013, 05h27
  2. [Upload] Comment récupérer un fichier ?
    Par belocom dans le forum Langage
    Réponses: 2
    Dernier message: 16/11/2007, 19h15
  3. [Upload] débutant, récupérer nom d'un fichier uploadé
    Par psgman113 dans le forum Langage
    Réponses: 1
    Dernier message: 08/05/2007, 17h24
  4. [Upload] Comment écraser un fichier après un upload
    Par pierrot10 dans le forum Langage
    Réponses: 1
    Dernier message: 21/03/2007, 14h30
  5. Réponses: 1
    Dernier message: 18/11/2005, 16h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo