upload-progress: Module de suivi de progression de téléchargement NGINX
Installation
Vous pouvez installer ce module dans toute distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-upload-progress
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-upload-progress
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_uploadprogress_module.so;
Ce document décrit nginx-module-upload-progress v0.9.4 publié le 15 mars 2025.
Introduction
nginx_uploadprogress_module est une implémentation d'un système de suivi de progression de téléchargement, qui surveille les téléchargements POST RFC1867 pendant qu'ils sont transmis aux serveurs en amont.
Il fonctionne en suivant les téléchargements proxyés par Nginx vers les serveurs en amont sans analyser le contenu téléchargé et offre une API web pour signaler la progression du téléchargement en Javascript, JSON ou tout autre format (avec l'aide de modèles).
Il fonctionne parce que Nginx agit comme un accélérateur d'un serveur en amont, stockant le contenu POST téléchargé sur disque, avant de le transmettre au serveur en amont. Chaque requête de téléchargement POST individuelle devrait contenir un identifiant unique de progression.
Ce module est Copyright (c) 2007-2012 Brice Figureau, et est sous licence BSD.
- Le code rbtree et shm_zone est basé sur le module Nginx limit_zone d'Igor Sysoev.
- Le code d'en-tête expire est basé sur le module Nginx header_filter d'Igor Sysoev.
L'idée JSON et le mécanisme sont basés sur Lighttpd mod_uploadprogress : http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back
AVERTISSEMENT : lorsqu'il est compilé avec --with-debug, ce module produira un grand nombre de messages de journal.
Changements incompatibles
v0.9.0 :
JSONP est maintenant la sortie par défaut des sondes de progression. Si vous dépendez de ce module pour servir la sortie java obsolète, utilisez :
upload_progress_java_output
dans l'emplacement de la sonde de progression.
Configuration
Chaque requête de téléchargement doit se voir attribuer un identifiant unique. Cet identifiant unique sera utilisé
pour stocker la requête et la référencer pour rapporter.
Cet identifiant peut être transmis soit comme un argument GET soit comme un en-tête HTTP dont le nom est X-Progress-ID.
upload_progress
| Syntaxe | upload_progress <zone_name> <zone_size> |
| Par défaut | aucun |
| Contexte | http |
Cette directive active le module de progression de téléchargement et réserve <zone_size> octets pour <zone_name> qui
sera utilisé pour stocker les informations de suivi par connexion.
track_uploads
| Syntaxe | track_uploads <zone_name> <timeout> |
| Par défaut | aucun |
| Contexte | location |
Cette directive active le suivi des téléchargements pour l'emplacement actuel. Chaque POST arrivant dans cet emplacement enregistrera
la requête dans le traqueur de progression de téléchargement <zone_name>.
Puisque Nginx ne prend pas encore en charge le téléchargement RFC 1867, l'emplacement doit être un emplacement proxy_pass ou fastcgi.
Le POST doit avoir un paramètre de requête appelé X-Progress-ID (ou un en-tête HTTP du même nom) dont la valeur est l'
identifiant unique utilisé pour obtenir des informations de progression. Si le POST ne contient pas de telles informations, le téléchargement ne sera pas suivi.
Les connexions suivies sont conservées au maximum <timeout> secondes après leur achèvement pour pouvoir fournir
des informations utiles aux sondes de progression de téléchargement.
AVERTISSEMENT : cette directive doit être la dernière directive de l'emplacement. Elle doit être dans un emplacement proxy_pass ou
fastcgi_pass.
report_uploads
| Syntaxe | report_uploads <zone_name> |
| Par défaut | aucun |
| Contexte | location |
Cette directive permet à un emplacement de signaler la progression du téléchargement qui est suivie par track_uploads pour <zone_name>.
Le document retourné est un texte Javascript avec les 4 résultats possibles par défaut :
-
La requête de téléchargement n'a pas encore été enregistrée ou est inconnue :
new Object({ 'state' : 'starting' }) -
La requête de téléchargement est terminée :
new Object({ 'state' : 'done' }) -
La requête de téléchargement a généré une erreur HTTP :
Un code d'erreur qui peut être utile pour le suivi côté client est 413 (entité de requête trop grande).new Object({ 'state' : 'error', 'status' : <error code> }) -
La requête de téléchargement est en cours :
new Object({ 'state' : 'uploading', 'received' : <size_received>, 'size' : <total_size>})
Il est possible de retourner du JSON pur au lieu de ce javascript (voir upload_progress_json_output).
Il est également possible de configurer complètement le format de réponse avec la directive upload_progress_template.
La requête HTTP vers cet emplacement doit avoir un paramètre X-Progress-ID ou un en-tête HTTP contenant un identifiant unique
valide d'un téléchargement en cours.
upload_progress_content_type
| Syntaxe | upload_progress_content_type <content_type> |
| Par défaut | text/javascript |
| Contexte | location |
Cette directive permet de changer le type de contenu de la réponse de la sonde de progression de téléchargement.
upload_progress_header
| Syntaxe | upload_progress_header <progress-id> |
| Par défaut | X-Progress-ID |
| Contexte | location |
Cette directive permet de changer le nom de l'en-tête de l'identifiant de progression.
upload_progress_jsonp_parameter
| Syntaxe | upload_progress_jsonp_parameter <callback_parameter> |
| Par défaut | callback |
| Contexte | location |
Cette directive permet de changer le nom du paramètre GET avec le nom de la fonction de rappel jsonp.
upload_progress_java_output
| Syntaxe | upload_progress_java_output |
| Par défaut | N/A |
| Contexte | location |
Cette directive définit tout pour être sorti comme du code javascript compatible avec eval().
upload_progress_json_output
| Syntaxe | upload_progress_json_output |
| Par défaut | N/A |
| Contexte | location |
Cette directive définit tout pour être sorti comme du JSON pur.
upload_progress_jsonp_output
| Syntaxe | upload_progress_jsonp_output |
| Par défaut | N/A |
| Contexte | location |
Cette directive définit tout pour être sorti comme JSONP (comme la sortie JSON, mais avec un rappel).
upload_progress_template
| Syntaxe | upload_progress_template <state> <template> |
| Par défaut | aucun |
| Contexte | location |
Cette directive peut être utilisée pour installer un modèle de réponse de progression. La liste des états disponibles est :
startinguploadingerrordone
Nginx remplacera la valeur des variables suivantes par leur valeur respective pour le téléchargement :
$uploadprogress_length: taille totale du téléchargement$uploadprogress_received: ce que le serveur a reçu jusqu'à présent$uploadprogress_status: code d'erreur en cas d'erreur HTTP$uploadprogress_callback: nom de la fonction de rappel jsonp si fourni comme paramètre de requête GET avec le nom 'callback'
Par exemple, pour retourner du XML (au lieu du Javascript ou JSON par défaut) :
upload_progress_content_type 'text/xml';
upload_progress_template starting '<upload><state>starting</state></upload>';
upload_progress_template uploading '<upload><state>uploading</state><size>$uploadprogress_length</size><uploaded>$uploadprogress_received</uploaded></upload>';
upload_progress_template done '<upload><state>done</state></upload>';
upload_progress_template error '<upload><state>error</state><code>$uploadprogress_status</code></upload>';
Exemple de réponse JSONP :
upload_progress_template starting "$uploadprogress_callback({ \"state\" : \"starting\"});";
upload_progress_template error "$uploadprogress_callback({ \"state\" : \"error\", \"status\" : $uploadprogress_status });";
upload_progress_template done "$uploadprogress_callback({ \"state\" : \"done\"});";
upload_progress_template uploading "$uploadprogress_callback({ \"state\" : \"uploading\", \"received\" : $uploadprogress_received, \"size\" : $uploadprogress_length });";
Exemple de configuration
http {
# réserve 1 Mo sous le nom 'proxied' pour suivre les téléchargements
upload_progress proxied 1m;
server {
listen 127.0.0.1 default;
server_name _ *;
root /path/to/root;
location / {
# proxy vers le serveur en amont
proxy_pass http://127.0.0.1;
proxy_redirect default;
# suivre les téléchargements dans la zone 'proxied'
# se souvenir des connexions pendant 30s après leur achèvement
track_uploads proxied 30s;
}
location ^~ /progress {
# rapporter les téléchargements suivis dans la zone 'proxied'
report_uploads proxied;
}
}
}
Exemple d'utilisation
Basé sur l'exemple du module Lighttpd mod_uploadprogress.
Tout d'abord, nous avons besoin d'un formulaire de téléchargement :
<form id="upload" enctype="multipart/form-data"
action="/upload.php" method="post"
onsubmit="openProgressBar(); return true;">
<input type="hidden" name="MAX_FILE_SIZE" value="30000000" />
<input name="userfile" type="file" label="fileupload" />
<input type="submit" value="Envoyer le fichier" />
</form>
Et une barre de progression pour visualiser la progression :
<div>
<div id="progress" style="width: 400px; border: 1px solid black">
<div id="progressbar"
style="width: 1px; background-color: black; border: 1px solid white">
</div>
</div>
<div id="tp">(progression)</div>
</div>
Ensuite, nous devons générer l'identifiant unique et lancer le téléchargement lors de l'action de soumission. Cela démarrera également le mécanisme de rapport de progression ajax.
interval = null;
function openProgressBar() {
/* générer un identifiant de progression aléatoire */
uuid = "";
for (i = 0; i < 32; i++) {
uuid += Math.floor(Math.random() * 16).toString(16);
}
/* patcher la balise action du formulaire pour inclure l'identifiant de progression */
document.getElementById("upload").action="/upload.php?X-Progress-ID=" + uuid;
/* appeler le mise à jour de progression toutes les 1000ms */
interval = window.setInterval(
function () {
fetch(uuid);
},
1000
);
}
function fetch(uuid) {
req = new XMLHttpRequest();
req.open("GET", "/progress", 1);
req.setRequestHeader("X-Progress-ID", uuid);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
/* parser JSON basique */
var upload = eval(req.responseText);
document.getElementById('tp').innerHTML = upload.state;
/* changer la largeur de la barre de progression intérieure */
if (upload.state == 'done' || upload.state == 'uploading') {
bar = document.getElementById('progressbar');
w = 400 * upload.received / upload.size;
bar.style.width = w + 'px';
}
/* nous avons terminé, arrêter l'intervalle */
if (upload.state == 'done') {
window.clearTimeout(interval);
}
}
}
}
req.send(null);
}
Logiciel compagnon
Ce logiciel peut également fonctionner avec le module de téléchargement Nginx de Valery Kholodkov : http://www.grid.net.ru/nginx/upload.en.html
Vous pouvez également utiliser les bibliothèques javascript suivantes côté client : http://drogomir.com/blog/2008/6/30/upload-progress-script-with-safari-support
Notez que lors de l'utilisation de jQuery AJAX pour le suivi de progression, tel que : https://github.com/drogus/jquery-upload-progress vous devez vous assurer de définir un paramètre de modèle upload_progress :
upload_progress_json_output
ou
upload_progress_jsonp_output
selon votre paramètre dataType jQuery AJAX.
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-upload-progress.