Zum Inhalt

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:

    new Object({ 'state' : 'error', 'status' : <error code> })
    
    Ein Fehlercode, der für den Client nützlich sein kann, ist 413 (Anfrageentität zu groß).

  • 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:

  • starting
  • uploading
  • error
  • done

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">
      &nbsp;
    </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.