Ein zweigigabyte großes Video über das WLAN eines Cafés hochzuladen, ist ein Akt des Optimismus. Man sieht zu, wie der Fortschrittsbalken mühsam auf siebzig Prozent kriecht, und dann flackert die Verbindung. Der Upload schlägt fehl. Wenn man es erneut versucht, erwartet der Server eine brandneue Datei. Man fängt wieder bei Null an. Für jeden, der eine Anwendung entwickelt, die nutzergenerierte Videos verarbeitet, ist dies kein Sonderfall. Es ist der Normalfall. Das tus-Protokoll wurde speziell entwickelt, um dieses Problem zu lösen. Es ist ein offener Standard, der über gewöhnliches HTTP läuft und Uploads ein „Gedächtnis“ verleiht. Sobald die Netzwerkverbindung wiederhergestellt ist, setzt die Dateiübertragung genau dort fort, wo sie unterbrochen wurde.
Warum Standard-Uploads scheitern
Standardmäßige Multipart-Datei-Uploads behandeln die gesamte Nutzlast als eine einzige Transaktion. Der Browser oder die App öffnet eine TCP-Verbindung, streamt die Bytes und erwartet am Ende ein 200 OK. Wenn die Verbindung unterbrochen wird, weil der Nutzer von LTE auf WLAN gewechselt hat oder der Laptop in den Ruhezustand gegangen ist, hat der Server keine Möglichkeit zu wissen, welche Bytes sicher angekommen sind. Die meisten Frameworks verwerfen die unvollständigen Daten einfach. Der Nutzer bleibt mit einem fehlgeschlagenen Formular und schlechter Laune zurück. Videodateien verstärken diesen Schmerz, da sie groß sind, oft von mobilen Geräten in instabilen Netzwerken hochgeladen werden und häufig in Formaten kodiert sind, die erst verarbeitet werden können, wenn die gesamte Datei vollständig ist.
Wie tus alles verändert
Tus denkt den Upload als eine zustandsbehaftete Konversation um, statt als eine einmalige Übertragung. Anstatt eine Datei in einem einzigen, kontinuierlichen Byte-Strom zu senden, unterteilt der Client die Nutzlast in Chunks. Noch wichtiger ist, dass der Server den Offset speichert – die genaue Anzahl der Bytes, die er bisher empfangen hat. Diese Zustandspersistenz ist es, die eine Fortsetzung ermöglicht. Das Protokoll ist bewusst einfach gehalten. Es benötigt keine WebSockets, gRPC oder proprietäre SDKs. Es nutzt die HTTP-Methoden, die Sie bereits kennen.
Die drei Requests, die die Fortsetzung ermöglichen
Jeder tus-Upload folgt einem vorhersehbaren Ablauf.
Zuerst sendet der Client einen POST-Request an einen bekannten tus-Endpunkt. Die Header beschreiben die Datei. Der Upload-Length-Header gibt die endgültige Größe in Bytes an, und optionale Metadaten wie der Dateiname oder der Content-Type werden im Upload-Metadata-Header als kommagetrennte Liste von Base64-kodierten Schlüssel-Wert-Paaren übertragen. Der Server erstellt eine leere Upload-Ressource und antwortet mit dem Status 201 Created sowie einem Location-Header, der auf eine eindeutige URL verweist. Diese URL ist für den Rest der Lebensdauer des Uploads die Adresse.
Als Nächstes folgt der PATCH-Request. Der Client sendet Chunks von Rohbinärdaten an diese eindeutige URL. Zwei kritische Header begleiten die Nutzlast. Content-Type muss application/offset+octet-stream sein, und Upload-Offset muss der Byte-Position entsprechen, an der dieser Chunk beginnt. Der Server überprüft, ob der Offset mit seinen eigenen Aufzeichnungen übereinstimmt. Wenn nicht, gibt der Server einen 409 Conflict zurück, um einen korrupten Zustand zu verhindern. Wenn alles passt, hängt der Server die Bytes an, aktualisiert seinen internen Offset und gibt eine 204 No Content-Antwort zusammen mit dem neuen Upload-Offset zurück. Die Chunk-Größe ist konfigurierbar, aber in der Praxis liegt sie meist zwischen einigen hundert Kilobyte und ein paar Megabyte. Kleinere Chunks erzeugen mehr HTTP-Overhead, ermöglichen aber eine schnellere Wiederherstellung nach Fehlern. Größere Chunks reduzieren die Anzahl der Roundtrips, verschwenden aber mehr Bandbreite, wenn sie während der Übertragung fehlschlagen.
Schließlich der HEAD-Request. Dies ist das Sicherheitsnetz. Wenn ein PATCH mitten in einem Chunk fehlschlägt – sagen wir nach drei Megabyte eines fünf Megabyte großen Segments –, bricht die Verbindung ab. Sobald der Client wieder Netzwerkzugriff hat, sendet er einen HEAD-Request an die Upload-URL. Der Server antwortet mit dem aktuellen Upload-Offset. Der Client vergleicht
