Start · Sprachen · JavaScript · Referenz · DecompressionStream

DecompressionStream

Schnittstelle

Ein <code>TransformStream</code>, der komprimierte Bytes (gzip, deflate, deflate-raw) als Datenstrom entgegennimmt und die dekomprimierten Bytes ausgibt.

seit JavaScript Baseline 2023: Chrome 80+, Edge 80+, Firefox 113+, Kategorie: webapi

Signatur

interface DecompressionStream (implements GenericTransformStream)

Beschreibung

DecompressionStream gehört zur Compression Streams API und entpackt komprimierte Binärdaten direkt im Browser bzw. in Node.js – ohne Bibliotheken wie pako oder fflate. Das Objekt stellt ein Paar aus writable (Eingang für komprimierte Bytes) und readable (Ausgang für entpackte Bytes) bereit und lässt sich deshalb einfach mit ReadableStream.prototype.pipeThrough() in eine Stream-Kette einhängen.

Typische Einsatzfälle sind das Entpacken von .gz-Dateien, die per fetch() geladen oder vom Nutzer über <input type="file"> ausgewählt wurden, das Lesen komprimierter Daten aus IndexedDB oder localStorage (Base64) sowie das Verarbeiten großer Datenmengen, ohne alles gleichzeitig im Speicher zu halten – die Dekompression erfolgt stückweise (chunk-basiert).

Unterstützt werden die Formate "gzip" (RFC 1952), "deflate" (zlib-Format, RFC 1950) und "deflate-raw" (reines DEFLATE ohne Header, RFC 1951). Die Eingabe-Chunks müssen BufferSource-Werte sein (ArrayBuffer, TypedArray, DataView); die Ausgabe besteht aus Uint8Array-Chunks. Für Text schaltet man anschließend einen TextDecoderStream dahinter.

Parameter

Name Typ Default Beschreibung
$format Pflicht "gzip" | "deflate" | "deflate-raw" Kompressionsformat der Eingabedaten. Ein unbekannter Wert wirft beim Konstruktor-Aufruf einen TypeError. Der Wert muss zum tatsächlichen Format passen, sonst schlägt die Dekompression mit einem Fehler fehl.

Rückgabewert

Typ
DecompressionStream
Beschreibung
Neue Instanz mit den schreibgeschützten Eigenschaften readable (ReadableStream<Uint8Array>, liefert die entpackten Bytes) und writable (WritableStream<BufferSource>, nimmt die komprimierten Bytes entgegen).

Beispiele

Gzip-Datei per fetch laden und als Text lesen

const loadGzipText = async (url) => {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);

  // Bytes entpacken und direkt als Text dekodieren
  const textStream = response.body
    .pipeThrough(new DecompressionStream('gzip'))
    .pipeThrough(new TextDecoderStream());

  return await new Response(textStream).text();
};

const text = await loadGzipText('/data/export.json.gz');
const data = JSON.parse(text);
console.log(`Datensätze: ${data.length}`);
Datensätze: 1250

Roundtrip: komprimieren und wieder entpacken

const compress = async (str) => {
  const stream = new Blob([str]).stream()
    .pipeThrough(new CompressionStream('deflate-raw'));
  return new Uint8Array(await new Response(stream).arrayBuffer());
};

const decompress = async (bytes) => {
  const stream = new Blob([bytes]).stream()
    .pipeThrough(new DecompressionStream('deflate-raw'));
  return await new Response(stream).text();
};

const original = 'Hallo Welt! '.repeat(100);
const packed = await compress(original);
const restored = await decompress(packed);

console.log(original.length, packed.length);
console.log(restored === original);
1200 22 true

Vom Nutzer gewählte .gz-Datei zeilenweise verarbeiten (writable/readable manuell)

const input = document.querySelector('#gzFile');

input.addEventListener('change', async () => {
  const file = input.files[0];
  if (!file) return;

  const ds = new DecompressionStream('gzip');
  // Datei in den Eingang schreiben (läuft parallel)
  file.stream().pipeTo(ds.writable).catch((err) => {
    console.error('Eingabe fehlgeschlagen:', err);
  });

  const reader = ds.readable
    .pipeThrough(new TextDecoderStream())
    .getReader();

  let chars = 0;
  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      chars += value.length; // Chunk verarbeiten
    }
    console.log(`Entpackt: ${chars} Zeichen`);
  } catch (err) {
    console.error('Keine gültige gzip-Datei:', err.name);
  }
});
Entpackt: 48213 Zeichen

// Wichtig · Fallstricke

  • Kein ZIP-Support: DecompressionStream entpackt nur einzelne gzip-/deflate-Datenströme, keine ZIP-Archive mit mehreren Dateien (dafür Bibliotheken wie fflate oder zip.js). Brotli ("br") und Zstandard werden bislang nicht breit unterstützt.
  • Format muss exakt passen: "deflate" erwartet einen zlib-Header, "deflate-raw" keinen. Falsches Format oder beschädigte bzw. abgeschnittene Daten führen zu einem TypeError beim Lesen – Fehler also immer mit try/catch bzw. .catch() behandeln.
  • Doppeltes Entpacken vermeiden: Liefert der Server Content-Encoding: gzip, entpackt der Browser bereits automatisch; ein zusätzlicher DecompressionStream schlägt dann fehl. Nur für Dateien einsetzen, die tatsächlich komprimiert als Nutzdaten ankommen (z. B. application/gzip).
  • Nur Binärdaten: Strings als Chunks führen zu einem TypeError; vorher mit TextEncoder oder Blob in Bytes umwandeln.
  • Sicherheit: Bei nicht vertrauenswürdigen Daten auf „Dekompressionsbomben“ achten – beim chunkweisen Lesen die entpackte Größe mitzählen und ab einem Limit per reader.cancel() abbrechen.
  • Kompatibilität: Seit 2023 in allen modernen Browsern (Firefox ab 113, Safari ab 16.4) verfügbar; "deflate-raw" kam in Chrome erst mit Version 103. In Node.js global ab Version 18 (vorher über node:stream/web). Ältere Umgebungen per Feature-Test 'DecompressionStream' in globalThis prüfen.