upload-progress: NGINX Upload-Fortschrittsverfolgungsmodul
Installation
Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:
- RedHat Enterprise Linux 7, 8, 9 und 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 und 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
Aktivieren Sie das Modul, indem Sie Folgendes an den Anfang von /etc/nginx/nginx.conf hinzufügen:
load_module modules/ngx_http_uploadprogress_module.so;
Dieses Dokument beschreibt nginx-module-upload-progress v0.9.4, veröffentlicht am 15. März 2025.
Einführung
nginx_uploadprogress_module ist eine Implementierung eines Upload-Fortschrittssystems, das RFC1867 POST-Uploads überwacht, während sie an Upstream-Server übertragen werden.
Es funktioniert, indem es die von Nginx an Upstream-Server weitergeleiteten Uploads verfolgt, ohne den hochgeladenen Inhalt zu analysieren, und bietet eine Web-API, um den Upload-Fortschritt in Javascript, JSON oder einem anderen Format (mithilfe von Vorlagen) zu melden.
Es funktioniert, weil Nginx als Beschleuniger eines Upstream-Servers agiert, der den hochgeladenen POST-Inhalt auf der Festplatte speichert, bevor er ihn an den Upstream-Server überträgt. Jede einzelne POST-Upload-Anfrage sollte einen einzigartigen Fortschrittsbezeichner enthalten.
Dieses Modul ist Copyright (c) 2007-2012 Brice Figureau und ist unter der BSD-Lizenz lizenziert.
- rbtree und shm_zone Code basieren auf Igor Sysoevs limit_zone Nginx-Modul.
- expire header Code basiert auf Igor Sysoevs header_filter Nginx-Modul.
Die JSON-Idee und die Mechanismusidee basieren auf Lighttpd mod_uploadprogress:
http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back
WARNUNG: Wenn es mit --with-debug kompiliert wird, erzeugt dieses Modul eine hohe Anzahl von Protokollnachrichten.
Inkompatible Änderungen
v0.9.0:
JSONP ist jetzt die Standardausgabe der Fortschrittsabfragen. Wenn Sie sich auf dieses Modul verlassen, um die veraltete Java-Ausgabe bereitzustellen, verwenden Sie:
upload_progress_java_output
im Fortschrittsabfrage-Standort.
Konfiguration
Jede Upload-Anfrage sollte mit einem einzigartigen Bezeichner versehen werden. Dieser einzigartige Bezeichner wird verwendet, um die Anfrage zu speichern und darauf zu verweisen, um den Fortschritt zu melden. Dieser Bezeichner kann entweder als GET-Argument oder als HTTP-Header mit dem Namen X-Progress-ID übertragen werden.
upload_progress
| Syntax | upload_progress <zone_name> <zone_size> |
| Standard | keine |
| Kontext | http |
Diese Direktive aktiviert das Upload-Fortschrittsmodul und reserviert <zone_size> Bytes für <zone_name>, das zur Speicherung der pro Verbindung verfolgten Informationen verwendet wird.
track_uploads
| Syntax | track_uploads <zone_name> <timeout> |
| Standard | keine |
| Kontext | location |
Diese Direktive aktiviert das Verfolgen von Uploads für den aktuellen Standort. Jeder POST, der an diesem Standort eingeht, registriert die Anfrage im <zone_name> Upload-Fortschrittstracker. Da Nginx RFC 1867 Uploads noch nicht unterstützt, muss der Standort ein proxy_pass oder fastcgi Standort sein. Der POST muss einen Abfrageparameter namens X-Progress-ID (oder einen HTTP-Header mit demselben Namen) haben, dessen Wert der einzigartige Bezeichner ist, der verwendet wird, um Fortschrittsinformationen zu erhalten. Wenn der POST keine solchen Informationen hat, wird der Upload nicht verfolgt. Die verfolgten Verbindungen werden maximal <timeout> Sekunden nach Abschluss aufbewahrt, um nützliche Informationen für die Upload-Fortschrittsabfragen bereitzustellen.
WARNUNG: Diese Direktive muss die letzte Direktive des Standorts sein. Sie muss sich in einem proxy_pass oder fastcgi_pass Standort befinden.
report_uploads
| Syntax | report_uploads <zone_name> |
| Standard | keine |
| Kontext | location |
Diese Direktive ermöglicht es einem Standort, den Upload-Fortschritt zu melden, der von track_uploads für <zone_name> verfolgt wird. Das zurückgegebene Dokument ist ein Javascript-Text mit standardmäßig 4 möglichen Ergebnissen:
-
Die Upload-Anfrage wurde noch nicht registriert oder ist unbekannt:
new Object({ 'state' : 'starting' }) -
Die Upload-Anfrage ist beendet:
new Object({ 'state' : 'done' }) -
Die Upload-Anfrage hat einen HTTP-Fehler erzeugt:
Ein Fehlercode, der für den Client nützlich sein kann, ist 413 (Anfrageentität zu groß).new Object({ 'state' : 'error', 'status' : <error code> }) -
Die Upload-Anfrage ist im Gange:
new Object({ 'state' : 'uploading', 'received' : <size_received>, 'size' : <total_size>})
Es ist möglich, reines JSON anstelle dieses Javascript zurückzugeben (siehe upload_progress_json_output). Es ist auch möglich, das Antwortformat vollständig mit der Direktive upload_progress_template zu konfigurieren.
Die HTTP-Anfrage an diesen Standort muss einen X-Progress-ID Parameter oder HTTP-Header enthalten, der einen gültigen einzigartigen Bezeichner eines laufenden Uploads enthält.
upload_progress_content_type
| Syntax | upload_progress_content_type <content_type> |
| Standard | text/javascript |
| Kontext | location |
Diese Direktive ermöglicht es, den Inhaltstyp der Antwort der Upload-Fortschrittsabfrage zu ändern.
upload_progress_header
| Syntax | upload_progress_header <progress-id> |
| Standard | X-Progress-ID |
| Kontext | location |
Diese Direktive ermöglicht es, den Headernamen des Fortschritts-ID zu ändern.
upload_progress_jsonp_parameter
| Syntax | upload_progress_jsonp_parameter <callback_parameter> |
| Standard | callback |
| Kontext | location |
Diese Direktive ermöglicht es, den Namen des GET-Parameters mit dem JSONP-Callback-Namen zu ändern.
upload_progress_java_output
| Syntax | upload_progress_java_output |
| Standard | N/A |
| Kontext | location |
Diese Direktive setzt alles auf Ausgabe als eval() javascript-kompatiblen Code.
upload_progress_json_output
| Syntax | upload_progress_json_output |
| Standard | N/A |
| Kontext | location |
Diese Direktive setzt alles auf Ausgabe als reines JSON.
upload_progress_jsonp_output
| Syntax | upload_progress_jsonp_output |
| Standard | N/A |
| Kontext | location |
Diese Direktive setzt alles auf Ausgabe als JSONP (ähnlich wie JSON-Ausgabe, aber mit Callback).
upload_progress_template
| Syntax | upload_progress_template <state> <template> |
| Standard | keine |
| Kontext | location |
Diese Direktive kann verwendet werden, um eine Fortschrittsantwortvorlage zu installieren. Die verfügbare Liste der Zustände ist:
startinguploadingerrordone
Nginx wird den Wert der folgenden Variablen durch ihren jeweiligen Wert für den Upload ersetzen:
$uploadprogress_length: Gesamtgröße des Uploads$uploadprogress_received: was der Server bisher erhalten hat$uploadprogress_status: Fehlercode im Falle eines HTTP-Fehlers$uploadprogress_callback: JSONP-Callback-Name, falls als GET-Abfrageparameter mit dem Namen 'callback' bereitgestellt
Beispielsweise, um XML (anstatt des standardmäßigen Javascript oder JSON) zurückzugeben:
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>';
Beispiel einer JSONP-Antwort:
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 });";
Konfigurationsbeispiel
http {
# reserviere 1MB unter dem Namen 'proxied' um Uploads zu verfolgen
upload_progress proxied 1m;
server {
listen 127.0.0.1 default;
server_name _ *;
root /path/to/root;
location / {
# proxy zum Upstream-Server
proxy_pass http://127.0.0.1;
proxy_redirect default;
# Uploads in der 'proxied' Zone verfolgen
# Verbindungen 30s nach Abschluss speichern
track_uploads proxied 30s;
}
location ^~ /progress {
# Uploads melden, die in der 'proxied' Zone verfolgt werden
report_uploads proxied;
}
}
}
Anwendungsbeispiel
Basierend auf dem Beispiel des Lighttpd mod_uploadprogress Moduls.
Zuerst benötigen wir ein Upload-Formular:
<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="Datei senden" />
</form>
Und eine Fortschrittsanzeige, um den Fortschritt zu visualisieren:
<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">(Fortschritt)</div>
</div>
Dann müssen wir den einzigartigen Bezeichner generieren und den Upload bei der Übermittlung starten. Dies wird auch den AJAX-Fortschrittsberichtsmechanismus starten.
interval = null;
function openProgressBar() {
/* generiere zufälligen progress-id */
uuid = "";
for (i = 0; i < 32; i++) {
uuid += Math.floor(Math.random() * 16).toString(16);
}
/* patch die form-action tag um die progress-id einzuschließen */
document.getElementById("upload").action="/upload.php?X-Progress-ID=" + uuid;
/* rufe den Fortschritts-Updater alle 1000ms auf */
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) {
/* einfacher JSON-Parser */
var upload = eval(req.responseText);
document.getElementById('tp').innerHTML = upload.state;
/* ändere die Breite der inneren Fortschrittsanzeige */
if (upload.state == 'done' || upload.state == 'uploading') {
bar = document.getElementById('progressbar');
w = 400 * upload.received / upload.size;
bar.style.width = w + 'px';
}
/* wir sind fertig, stoppe das Intervall */
if (upload.state == 'done') {
window.clearTimeout(interval);
}
}
}
}
req.send(null);
}
Begleitsoftware
Diese Software kann auch mit Valery Kholodkovs Nginx Upload-Modul arbeiten:
http://www.grid.net.ru/nginx/upload.en.html
Sie können auch die folgenden Javascript-Bibliotheken auf der Client-Seite verwenden:
http://drogomir.com/blog/2008/6/30/upload-progress-script-with-safari-support
Beachten Sie, dass Sie beim Verwenden von jQuery AJAX zur Fortschrittsüberwachung, wie z.B.:
https://github.com/drogus/jquery-upload-progress
sicherstellen sollten, dass Sie einen upload_progress Template-Parameter setzen:
upload_progress_json_output
oder
upload_progress_jsonp_output
je nach Ihrer jQuery AJAX dataType-Einstellung.
GitHub
Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-upload-progress.