Der Download mehrerer Dateien (z.B. PDFs) wird üblicherweise als ZIP-Archiv angeboten. Nach Auswahl der Dateien muss der Nutzer in der Regel warten, bis das Archiv erstellt wurde. Wir zeigen, wie das ZIP-Archiv während des Downloads zusammengestellt werden kann – ohne Wartezeit. Dabei können die Dateinamen im ZIP-Archiv weiterhin bei jedem Download individuell angepasst werden.

Was ist ein ZIP-Archiv?

Ein ZIP-Archiv ist eine Aneinanderreihung von Dateien mit Metadaten, optional komprimiert oder verschlüsselt, sowie einem Index aller Dateien am Ende. Die Metadaten jeder Datei enthalten einen Fehlererkennungscode (CRC32).

Ein ZIP-Archiv besteht aus:

  • Dateien zusammen mit ihren Metadaten
  • Einem Index der Dateien (nur die Metadaten) und deren Positionen im Archiv

Die Metadaten jeder Datei bestehen aus:

  • Informationen für den Endnutzer: Dateiname, Änderungsdatum, …
  • Technischen Metadaten: Fehlererkennungscode (CRC32), benötigte ZIP-Version, …

Die ZIP-Spezifikation ist öffentlich einsehbar.

Der CRC32-Wert jeder Datei kann zusammen mit anderen Metadaten im Voraus berechnet und gemeinsam mit den für den Download vorgesehenen Dateien gespeichert werden. Das ZIP-Archiv kann dann mit minimalem Rechenaufwand während des Downloads aus den Metadaten und Dateien zusammengesetzt werden.

Kompression ist oft nicht erforderlich

In ZIP-Archiven wird die Kompression pro Datei angewendet, nicht auf das Archiv als Ganzes. Ähnlichkeiten zwischen Dateien (z.B. wenn dieselbe Datei mehrfach enthalten ist) werden nicht zur Kompression genutzt.

Daten in gängigen Formaten wie JPEG (Bilder), oder MP3 oder OGG (Audio) sind üblicherweise bereits komprimiert. Die Kompression von PDFs ohne eingebettete Medien kann zwar einen geringen Effekt haben; bei PDFs mit wenigen Seiten liegt der Grund für die Kompression jedoch meist in enthaltenen Medien, die sich durch ZIP nicht wesentlich weiter verkleinern lassen.

Eine Demo in T-SQL

Wir haben einen Proof of Concept in T-SQL umgesetzt, der für Szenarien gedacht ist, in denen Dateien in einer Datenbank gespeichert sind. Der Ansatz lässt sich leicht auf andere Programmiersprachen, Frameworks, und Speicherorte übertragen.

Das soll keine Empfehlung zur Speicherung großer Mengen unstrukturierter Daten in einer Datenbank darstellen.

Der Quelltext ist auf unserer GitHub-Seite verfügbar: https://github.com/ddunicorn/zip.schema . Das folgende Listing zeigt, wie er zur Erstellung eines ZIP-Archivs verwendet werden kann.

declare @contents_1 varbinary(max) = convert(varbinary(max), 'contents_1');
declare @contents_2 varbinary(max) = convert(varbinary(max), 'contents_2');

declare @zip_input ZIP.TYPE_FILE_LIST;
insert @zip_input (file_name, content, file_date, crc32, content_length) values
    ('test/test', @contents_1, '2021-01-01', zip.f_crc32(@contents_1), LEN(@contents_1)),
    ('test/test2', @contents_2, GETDATE(), zip.f_crc32(@contents_2), LEN(@contents_2))

-- Demo output
declare @zip_file varbinary(max) = (select ZIP.F_ZIP(@zip_input));
select ' echo "' 
    + CAST('' as xml).value('xs:base64Binary(sql:variable("@zip_file"))', 'varchar(max)')
    + '" | base64 -d > sql.zip'