5505 links
  • GuiGui's Show

  • Home
  • Login
  • RSS Feed
  • Tag cloud
  • Picture wall
  • Daily
Links per page: 20 50 100
page 1 / 1
  • Barre de progression d'un upload web calculée côté serveur

    Je me suis toujours demandé comment fonctionne les barres de progression d'un téléchargement / téléversement que l'on trouve sur les sites web : comment le code du site web peut-il être au courant de l'avancement d'une telle action puisqu'il est exécuté une fois l'upload terminé ?

    Au temps du module PHP pour Apache httpd, je me disais que, vu qu'il s'agit d'un module, il est incrusté au cœur d'Apache httpd donc il doit certainement disposer d'infos supplémentaires. Mais quid des installations dans lesquelles le serveur web est uniquement un reverse proxy vers un serveur d'applications (FastCGI, PHP-FPM, Python uwsgi) ?

    La première réponse qui vient à l'esprit est : on surveille la progression de l'upload entièrement côté client avec Ajax.

    J'ignorais qu'il est également possible de surveiller l'upload côté serveur. Enfin, pas totalement, puisqu'il faudra toujours de l'Ajax pour actualiser la barre de progression. Mais le reste est fait côté serveur.


    Fonctionnement d'une barre de progression côté serveur

    A priori, tout le monde s'est mis d'accord sans pour autant produire une norme (en tout cas, le RFC 1867, souvent cité, normalise l'envoi de fichiers avec un formulaire web, mais pas la mesure de la progression d'un upload) :

    • Le script côté client génère un identifiant unique pour chaque upload ;

    • Le navigateur web lance l'upload ;

    • Le serveur fait les calculs de la progression de l'upload ;

    • En parallèle de l'upload, le client interroge le serveur grâce à Ajax (requêtes asynchrones) en utilisant une URL convenue à l'avance choisie par l'application et en rappelant l'identifiant unique de l'upload. Exemple : XHR GET https://www.monorganisation.example/progressbarupload/upload_progress?X-Progress-ID=42122089-d6dd-4570-9ded-09e75f8a50d2 ;

    • Le serveur répond du JSON. Exemple : « { "state" : "uploading", "received" : 49478497, "size" : 65730134 } ».

    • Le client actualise la barre de progression, puis refait une requête au serveur web afin de connaître l'avancement de l'upload, donc retour au 4e point ci-dessus ;



    Quand j'écris « le serveur fait » ceci ou cela, de quel composant précis est-ce que je parle ?

    • Cela peut être PHP, nativement ou couplé au module APC. Dans ces deux cas, le suivi de la progression fonctionne uniquement avec le module PHP pour Apache httpd, pas en FastCGI ni avec PHP-FPM ;

    • Cela peut être le serveur web. Il existe un module pour nginx, un module pour Apache httpd, un module pour Lighttpd, etc. Dans Debian GNU/Linux, celui pour nginx est activé par défaut, celui pour Apache httpd est disponible dans le paquet libapache2-mod-upload-progress. Celui pour nginx est plutôt bien documenté (peut mieux faire sur les valeurs par défaut des paramètres, par exemple) alors que celui pour Apache httpd ne l'est quasiment pas (ça ne permet pas de comprendre que l'URL à laquelle récupérer les rapports de progression est configurable, par exemple).


    Configurer nginx

    • Dans le bloc http du fichier ngnix.conf, il faut ajouter : upload_progress uploadp 1m;. On réserve un espace mémoire d'un mégaoctet nommé « uploadp » pour le suivi des uploads ;

    • Dans le serveur virtuel, dans le bloc location qui envoie les requêtes vers un serveur d'applications, il faut ajouter track_uploads uploadp 30s. On surveille tous les uploads en les enregistrant dans l'espace mémoire « uploadp » défini ci-dessus. On conserve la trace d'un upload jusqu'à 30 secondes après sa complétion ;

    • Dans le serveur virtuel, on ajoute un nouveau bloc location capturant l'URL à laquelle l'application est programmée pour venir chercher les informations concernant un upload à coup de XMLHTTPRequest. nginx répondra aux requêtes GET qu'il recevra à cette URL avec les informations concernant un upload dont l'identifiant est passé en argument si celui-ci a été surveillé dans l'espace mémoire « uploadp » :

      location ^~ /progressbarupload/upload_progress {
          upload_progress_json_output
          report_uploads uploadp;
      }


    • On recharge la configuration : sudo systemctl reload nginx.

    Notons que le module nginx prend en charge JSONP, JSON with Padding, qui encapsule les données dans un appel de fonction afin de contourner les restrictions inter-domaines : la récupération d'un fichier depuis un autre domaine avec XMLHTTPRequest est interdite par défaut par les navigateurs web sauf si l'on positionne des en-têtes CORS sur le site web sur lequel les données doivent être récupérées, alors que la récupération d'un script JavaScript sans utiliser XMLHTTPRequest est autorisée par défaut. Pour activer un retour au format JSONP, il faut remplacer upload_progress_json_output par upload_progress_jsonp_output.


    Configurer Apache httpd :

    • On installe le module (il sera activé et httpd sera redémarré) : sudo apt-get install libapache2-mod-upload-progress ;

    • Dans le serveur virtuel, dans le bloc location qui envoie les requêtes vers un serveur d'applications, il faut ajouter TrackUploads On ;

    • Dans le serveur virtuel, on ajoute un nouveau bloc location capturant à l'URL à laquelle l'application est programmée pour venir chercher les informations concernant un upload à coup de XMLHTTPRequest. nginx répondra aux requêtes GET qu'il recevra à cette URL avec les informations concernant un upload dont l'indentifiant est passé en argument :

      <Location ~ '^/progressbarupload/upload_progress'>
          ReportUploads On
      </Location>


    • On recharge la configuration : sudo systemctl restart apache2.

    Le module Apache httpd prend aussi en charge JSONP. Pour l'activer, il suffit d'ajouter le paramètre callback=<nom_désiré_pour_la_callback> à la requête HTTP GET qui viendra consulter le rapport d'avancement de l'upload produit par le serveur, il y a rien à activer dans la configuration du serveur web.

    Sun Nov 15 19:14:33 2020 - permalink -
    - http://shaarli.guiguishow.info/?TtmNbA
Links per page: 20 50 100
page 1 / 1
Mentions légales identiques à celles de mon blog | CC BY-SA 3.0

Shaarli - The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community