Marcel Cremer
20. Februar 2023

Dateien von Microsoft Azure oder Amazon S3 Batch-downloaden

Gepostet am 20. Februar 2023
6 Minuten  • 1079 Wörter  • Andere Sprachen:  English

Wenn du in der Cloud arbeitest, bist du wahrscheinlich schon irgendwann einmal auf die Anforderung gestoßen, Dateien aus dem Cloud-Speicher im Batch herunterzuladen. Egal, ob du die Berichte des Vorjahres, vom Benutzer hochgeladene Dateien oder andere zur Verfügung stellen möchtest - das Bereitstellen eines Datenarchivs ist ein gar nicht so ungewöhnlicher Anwendungsfall. Als ich versucht habe, eine native Lösung mit Microsoft Azure zu finden, gab es nur Beispiele wie hier (MSDN, extern), wo Dateien entweder einzeln oder parallel heruntergeladen werden, aber nicht als Batch-Download mit nur einem Link bereitgestellt werden konnten.

In diesem Artikel werde ich zuerst meine Reise zur aktuellen Lösung erklären. Im Fall von TLDR, klicke hier.

Die “einfache” serverseitige Lösung

Bei meinem ersten Versuch habe ich versucht, die Anforderungen mit so einem “Best-Practice”-Ansatz zu lösen - und bin leider kläglich gescheitert. Der implementierte Ansatz sah in etwa so aus:

Der Client fordert das Archiv über eine RESTful-API an

Für ein paar kleine Dateien funktioniert dieser Ansatz sogar sehr gut. Sobald jedoch die Datenmenge wächst, stößt man auf einige ernsthafte Probleme:

…und wahrscheinlich einige andere, die mir gerade nicht einfallen. Insgesamt ist das keine besondere Nachhaltige Lösung, weil sie eine Menge Potenzial hat, zu versagen (und ich habe vermutlich jede Fehlerquelle gefunden).

Die “etwas-komplexere” serverseitige Lösung

Weil das Ausliefern der Daten in Echtzeit nicht immer möglich ist, war meine nächste Lösung, den Job “auszulagern”, was auch eine Inspiration für meinen Artikel zu KEDA war. Der Ablauf für den Client hat sich nun ein bisschen geändert und dafür konnte die Arbeit komplett im Hintergrund erledigt werden:

Der Client fordert das Archiv über eine RESTful-API an Der Server antwortet, dass die Anforderung im Hintergrund bearbeitet wird

Der Ablauf des Jobs war dann im Grunde genommen der gleiche, der vorher auf dem Server ausgeführt wurde. Anstatt das Ergebnise jedoch an den Client zu senden, wurde es erneut als Zip-Archiv auf dem Azure Blob abgelegt, und dem Client am Ende nur noch der fertige Link mitgeteilt.

Der Hintergrundjob hat allerdings ein paar neue Probleme erzeugt:

Also selbst jetzt, wo wir die Arbeit vom Server weg verlagert haben, bleibt immer noch eine lange Liste an Dingen, die schief gehen können. Außerdem ist nun sowohl der Prozess, als auch das Management der dahinterliegenden Infrastruktur deutlich komplexer geworden. Wenn wir die Dateien doch nur direkt von Azure oder Amazon S3 an den User schicken könnten. Aber das ist ja nicht möglich… oder, vielleicht doch?

Eine Client-basierte Lösung zum Download des Zip-Archivs

Gehen wir noch einmal zwei Schritte zurück zu den ursprünglichen Anforderungen. Wir wollen

Ist das überhaupt möglich, ohne dass Microsoft Azure BLOBs oder Amazon S3 Batch-Downloads anbietet? Ja, das ist es!

Ich habe in diesem Repository einen Proof-of-concept bereitgestellt. Die Demo ist in Vue geschrieben, aber um zu verstehen was passiert, sind wirklich keine Vue-Kenntnisse nötig. Der Ablauf ist wie folgt:

Wenn du auf den Client Batch Download Example-Button klickst, wird die downloadAndStoreAsZip-Funktion angetriggert, die versucht, 1000 Dateien von einem Roboter-Bilder-Generator namens robohash.org (welcher übrigens großartig ist) herunterzuladen. Per default ist die downloadInParallel-Funktion so geschrieben, dass sie fetch-Promises für 10 Bilder pro Batch-Durchlauf generiert, und diese als BLOB in den RAM lädt. Bei Bedarf, kannst du hier auch den “throttle” einstellen, um zwischen den einzelnen Batch-Downloads ein paar Sekunden zu warten. Ansonsten macht die Funktion einfach weiter, bis alles heruntergeladen ist. Währenddessen wird nach jedem Batch-Download der Status aktualisiert, sodass wir dem Client mitteilen können, wie weit wir mit dem Download sind. Als letztes kommt die JSZip-Bibliothek ins Spiel, mit der wir die Dateien in der richtigen Ordnerstruktur zippen und schlussendlich im Browser zum Speichern auf die Festplatte anbieten.

Azure Batch Download Progress Bar

Diese Lösung ist deutlich besser, als alle, die wir davor hatten:

Nicht verheimlichen möchte ich an der Stelle, dass es auch zwei Nachteile bei dieser Methode gibt:

Für den ersten Nachteil gibt es bei Bedarf eine Lösung, die sogar in der von uns genutzten FileSaver-Bibliothek verlinkt ist: StreamSaver macht es möglich, noch während des Downloads die BLOBs direkt auf die Festplatte des Clients zu schreiben und somit nicht bis zum Ende des kompletten Vorgangs im RAM vorhalten zu müssen.

Zum zweiten Punkt kann ich nach einigem Abwägen sagen, dass ich bereit bin, diesen für meine Zwecke zu akzeptieren, weil die Vorteile hier die Nachteile bei weitem überwiegen.

Follow me

Ich arbeite an der Saas-Plattform MOBIKO, baue Teams auf und gebe manchmal Talks.