UNPKG

5.84 kBMarkdownView Raw
1# node-stream-zip ![CI Checks](https://github.com/antelle/node-stream-zip/workflows/CI%20Checks/badge.svg)
2
3node.js library for reading and extraction of ZIP archives.
4Features:
5
6- it never loads entire archive into memory, everything is read by chunks
7- large archives support
8- all operations are non-blocking, no sync i/o
9- fast initialization
10- no dependencies, no binary addons
11- decompression with built-in zlib module
12- deflate, sfx, macosx/windows built-in archives
13- ZIP64 support
14
15## Installation
16
17```sh
18npm i node-stream-zip
19```
20
21## Usage
22
23There are two APIs provided:
241. [promise-based / async](#async-api)
252. [callbacks](#callback-api)
26
27It's recommended to use the new, promise API, however the legacy callback API
28may be more flexible for certain operations.
29
30### Async API
31
32Open a zip file
33```javascript
34const StreamZip = require('node-stream-zip');
35const zip = new StreamZip.async({ file: 'archive.zip' });
36```
37
38Stream one entry to stdout
39```javascript
40const stm = await zip.stream('path/inside/zip.txt');
41stm.pipe(process.stdout);
42stm.on('end', () => zip.close());
43```
44
45Read a file as buffer
46```javascript
47const data = await zip.entryData('path/inside/zip.txt');
48await zip.close();
49```
50
51Extract one file to disk
52```javascript
53await zip.extract('path/inside/zip.txt', './extracted.txt');
54await zip.close();
55```
56
57List entries
58```javascript
59const entriesCount = await zip.entriesCount;
60console.log(`Entries read: ${entriesCount}`);
61
62const entries = await zip.entries();
63for (const entry of Object.values(entries)) {
64 const desc = entry.isDirectory ? 'directory' : `${entry.size} bytes`;
65 console.log(`Entry ${entry.name}: ${desc}`);
66}
67
68// Do not forget to close the file once you're done
69await zip.close();
70```
71
72Extract a folder from archive to disk
73```javascript
74fs.mkdirSync('extracted');
75await zip.extract('path/inside/zip/', './extracted');
76await zip.close();
77```
78
79Extract everything
80```javascript
81fs.mkdirSync('extracted');
82const count = await zip.extract(null, './extracted');
83console.log(`Extracted ${count} entries`);
84await zip.close();
85```
86
87When extracting a folder, you can listen to `extract` event
88```javascript
89zip.on('extract', (entry, file) => {
90 console.log(`Extracted ${entry.name} to ${file}`);
91});
92```
93
94`entry` event is generated for every entry during loading
95```javascript
96zip.on('entry', entry => {
97 // you can already stream this entry,
98 // without waiting until all entry descriptions are read (suitable for very large archives)
99 console.log(`Read entry ${entry.name}`);
100});
101```
102
103### Callback API
104
105Open a zip file
106```javascript
107const StreamZip = require('node-stream-zip');
108const zip = new StreamZip({ file: 'archive.zip' });
109
110// Handle errors
111zip.on('error', err => { /*...*/ });
112```
113
114List entries
115```javascript
116zip.on('ready', () => {
117 console.log('Entries read: ' + zip.entriesCount);
118 for (const entry of Object.values(zip.entries())) {
119 const desc = entry.isDirectory ? 'directory' : `${entry.size} bytes`;
120 console.log(`Entry ${entry.name}: ${desc}`);
121 }
122 // Do not forget to close the file once you're done
123 zip.close();
124});
125```
126
127Stream one entry to stdout
128```javascript
129zip.on('ready', () => {
130 zip.stream('path/inside/zip.txt', (err, stm) => {
131 stm.pipe(process.stdout);
132 stm.on('end', () => zip.close());
133 });
134});
135```
136
137Extract one file to disk
138```javascript
139zip.on('ready', () => {
140 zip.extract('path/inside/zip.txt', './extracted.txt', err => {
141 console.log(err ? 'Extract error' : 'Extracted');
142 zip.close();
143 });
144});
145```
146
147Extract a folder from archive to disk
148```javascript
149zip.on('ready', () => {
150 fs.mkdirSync('extracted');
151 zip.extract('path/inside/zip/', './extracted', err => {
152 console.log(err ? 'Extract error' : 'Extracted');
153 zip.close();
154 });
155});
156```
157
158Extract everything
159```javascript
160zip.on('ready', () => {
161 fs.mkdirSync('extracted');
162 zip.extract(null, './extracted', (err, count) => {
163 console.log(err ? 'Extract error' : `Extracted ${count} entries`);
164 zip.close();
165 });
166});
167```
168
169Read a file as buffer in sync way
170```javascript
171zip.on('ready', () => {
172 const data = zip.entryDataSync('path/inside/zip.txt');
173 zip.close();
174});
175```
176
177When extracting a folder, you can listen to `extract` event
178```javascript
179zip.on('extract', (entry, file) => {
180 console.log(`Extracted ${entry.name} to ${file}`);
181});
182```
183
184`entry` event is generated for every entry during loading
185```javascript
186zip.on('entry', entry => {
187 // you can already stream this entry,
188 // without waiting until all entry descriptions are read (suitable for very large archives)
189 console.log(`Read entry ${entry.name}`);
190});
191```
192
193## Options
194
195You can pass these options to the constructor
196- `storeEntries: true` - you will be able to work with entries inside zip archive, otherwise the only way to access them is `entry` event
197- `skipEntryNameValidation: true` - by default, entry name is checked for malicious characters, like `../` or `c:\123`, pass this flag to disable validation errors
198
199## Methods
200
201- `zip.entries()` - get all entries description
202- `zip.entry(name)` - get entry description by name
203- `zip.stream(entry, function(err, stm) { })` - get entry data reader stream
204- `zip.entryDataSync(entry)` - get entry data in sync way
205- `zip.close()` - cleanup after all entries have been read, streamed, extracted, and you don't need the archive
206
207## Building
208
209The project doesn't require building. To run unit tests with [nodeunit](https://github.com/caolan/nodeunit):
210```sh
211npm test
212```
213
214## Known issues
215
216- [utf8](https://github.com/rubyzip/rubyzip/wiki/Files-with-non-ascii-filenames) file names
217- AES encrypted files
218
219## Contributors
220
221ZIP parsing code has been partially forked from [cthackers/adm-zip](https://github.com/cthackers/adm-zip) (MIT license).