node.js library for reading and extraction of ZIP archives
npm install @drorgl/node-stream-zipnode.js library for reading and extraction of ZIP archives.
Features:
- it never loads entire archive into memory, everything is read by chunks
- large archives support
- all operations are non-blocking, no sync i/o
- fast initialization
- no dependencies, no binary addons
- decompression with built-in zlib module
- deflate, deflate64, sfx, macosx/windows built-in archives
- ZIP64 support
$ npm install @drorgl/node-stream-zip
Open a zip file
``typescript
import { StreamZip } from "@drorgl/node-stream-zip";
const zip = new StreamZip({
file: 'archive.zip',
storeEntries: true
});
// Handle errors
zip.on('error', err => { /.../ });
`
List entries
`typescript${entry.size} bytes
zip.on('ready', () => {
console.log('Entries read: ' + zip.entriesCount);
for (const entry of Object.values(zip.entries())) {
const desc = entry.isDirectory ? 'directory' : ;Entry ${entry.name}: ${desc}
console.log();`
}
// Do not forget to close the file once you're done
zip.close()
});
Stream one entry to stdout
`typescript`
zip.on('ready', () => {
zip.stream('path/inside/zip.txt', (err, stm) => {
stm.pipe(process.stdout);
stm.on('end', () => zip.close());
});
});
Extract one file to disk
`typescript`
zip.on('ready', () => {
zip.extract('path/inside/zip.txt', './extracted.txt', err => {
console.log(err ? 'Extract error' : 'Extracted');
zip.close();
});
});
Extract a folder from archive to disk
`typescript`
zip.on('ready', () => {
fs.mkdirSync('extracted');
zip.extract('path/inside/zip/', './extracted', err => {
console.log(err ? 'Extract error' : 'Extracted');
zip.close();
});
});
Extract everything
`typescriptExtracted ${count} entries
zip.on('ready', () => {
fs.mkdirSync('extracted');
zip.extract(null, './extracted', (err, count) => {
console.log(err ? 'Extract error' : );`
zip.close();
});
});
Read a file as buffer in sync way
`typescript`
zip.on('ready', () => {
const data = zip.entryDataSync('path/inside/zip.txt');
zip.close();
});
When extracting a folder, you can listen to extract event`typescriptExtracted ${entry.name} to ${file}
zip.on('extract', (entry, file) => {
console.log();`
});
entry event is generated for every entry during loading`typescriptRead entry ${entry.name}
zip.on('entry', entry => {
// you can already stream this entry,
// without waiting until all entry descriptions are read (suitable for very large archives)
console.log();`
});
You can pass these options to the constructor
- storeEntries: true - you will be able to work with entries inside zip archive, otherwise the only way to access them is entry eventskipEntryNameValidation: true
- - by default, entry name is checked for malicious characters, like ../ or c:\123, pass this flag to disable validation errors
- zip.entries() - get all entries descriptionzip.entry(name)
- - get entry description by namezip.stream(entry, function(err, stm) { })
- - get entry data reader streamzip.entryDataSync(entry)
- - get entry data in sync wayzip.close()
- - cleanup after all entries have been read, streamed, extracted, and you don't need the archive
The project doesn't require building. To run unit tests with nodeunit:
$ npm test
=============================== Coverage summary ===============================
Statements : 87.22% ( 471/540 )
Branches : 73.46% ( 191/260 )
Functions : 94.05% ( 79/84 )
Lines : 87.67% ( 462/527 )
================================================================================
``- utf8 file names
- AES encrypted files
ZIP parsing code has been partially forked from cthackers/adm-zip (MIT license).