Unzip Stream

0.3.4 · maintenance · verified Tue Apr 21

unzip-stream is a Node.js library for processing zip files using a streaming API. It provides mechanisms to parse zip file contents entry by entry or extract an entire archive to a directory. The current stable version is 0.3.4, with a release cadence that appears to be maintenance-focused rather than frequent feature additions. Key differentiators include its streaming engine, which aims to handle zip files that might cause issues with older libraries like `unzip` or `unzipper`, and its reliance solely on Node.js's built-in zlib for inflation, avoiding compiled dependencies. It supports Zip64 for archives with files larger than 4GB. However, the library acknowledges that the zip file format is not inherently optimized for streaming, suggesting alternatives like `yauzl` or `decompress-zip` for scenarios where the complete zip file is available and random access is preferred. It lacks support for encrypted (password-protected) zips and symlinks.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to parse a zip file, iterate through its entries, and selectively extract a specific file. It highlights the crucial `autodrain()` method for unconsumed entries and proper event handling.

import fs from 'fs';
import path from 'path';
import * as unzip from 'unzip-stream';

const archivePath = path.resolve('./example.zip');
const outputPath = path.resolve('./extracted_files');

// Create a dummy zip file for demonstration if it doesn't exist
if (!fs.existsSync(archivePath)) {
  console.warn('Creating a dummy example.zip for quickstart. In a real scenario, use a valid zip file.');
  const JSZip = await import('jszip'); // Dynamic import for JSZip
  const zip = new JSZip.default();
  zip.file('hello.txt', 'Hello, Unzip Stream!');
  zip.file('folder/world.txt', 'World!');
  const content = await zip.generateAsync({ type: 'nodebuffer' });
  fs.writeFileSync(archivePath, content);
}

// Ensure output directory exists
if (!fs.existsSync(outputPath)) {
  fs.mkdirSync(outputPath, { recursive: true });
}

fs.createReadStream(archivePath)
  .pipe(unzip.Parse())
  .on('entry', function (entry) {
    const filePath = entry.path;
    const type = entry.type; // 'Directory' or 'File'
    const size = entry.size; // might be undefined in some archives

    console.log(`Processing entry: ${filePath} (Type: ${type}, Size: ${size || 'unknown'})`);

    if (type === 'File' && filePath === 'hello.txt') {
      const writeStream = fs.createWriteStream(path.join(outputPath, path.basename(filePath)));
      entry.pipe(writeStream);
      writeStream.on('finish', () => console.log(`Extracted ${filePath}`));
    } else {
      // Important: Call autodrain() for entries you don't consume to prevent stream from getting stuck.
      entry.autodrain();
      if (type === 'File') console.log(`Skipping extraction for ${filePath}, autodraining.`);
    }
  })
  .on('close', () => {
    console.log('Finished parsing the archive. Check output in:', outputPath);
  })
  .on('error', (err) => {
    console.error('An error occurred during parsing:', err);
  });

view raw JSON →