0
# Random Access Interface
1
2
Promise-based API for opening ZIP files from multiple sources (filesystem, URLs, S3, buffers) and accessing their contents with random access patterns. This high-level interface provides convenient methods for reading ZIP files without streaming, ideal for applications that need to inspect or selectively extract files.
3
4
## Capabilities
5
6
### File System Access
7
8
Opens ZIP files from local filesystem paths.
9
10
```javascript { .api }
11
/**
12
* Opens a ZIP file from the filesystem
13
* @param path - File system path to the ZIP file
14
* @param options - Optional configuration object
15
* @returns Promise resolving to Directory object
16
*/
17
static async file(path: string, options?: OpenOptions): Promise<Directory>;
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const unzipper = require("unzipper");
24
25
// Basic file opening
26
const directory = await unzipper.Open.file("archive.zip");
27
console.log(`Archive contains ${directory.files.length} files`);
28
29
// List all files
30
directory.files.forEach(file => {
31
console.log(`${file.type}: ${file.path}`);
32
});
33
34
// Find specific file
35
const readme = directory.files.find(f => f.path === "README.md");
36
if (readme) {
37
const content = await readme.buffer();
38
console.log(content.toString());
39
}
40
41
// Extract specific files
42
const configFile = directory.files.find(f => f.path.endsWith("config.json"));
43
if (configFile) {
44
const configStream = configFile.stream();
45
configStream.pipe(fs.createWriteStream("config.json"));
46
}
47
```
48
49
### URL Access
50
51
Opens ZIP files from HTTP/HTTPS URLs using a provided request library.
52
53
```javascript { .api }
54
/**
55
* Opens a ZIP file from a URL
56
* @param requestLibrary - HTTP request library (e.g., 'request' module)
57
* @param url - URL to the ZIP file
58
* @param options - Optional configuration object
59
* @returns Promise resolving to Directory object
60
*/
61
static async url(requestLibrary: any, url: string, options?: OpenOptions): Promise<Directory>;
62
```
63
64
**Usage Examples:**
65
66
```javascript
67
const request = require("request");
68
69
// Download and open ZIP file
70
const directory = await unzipper.Open.url(request, "https://example.com/archive.zip");
71
72
// Process files from remote ZIP
73
for (const file of directory.files) {
74
if (file.type === "File" && file.path.endsWith(".txt")) {
75
const content = await file.buffer();
76
console.log(`${file.path}: ${content.length} bytes`);
77
}
78
}
79
80
// Stream large file from remote ZIP
81
const largeFile = directory.files.find(f => f.path === "data/large-dataset.csv");
82
if (largeFile) {
83
largeFile.stream().pipe(fs.createWriteStream("dataset.csv"));
84
}
85
```
86
87
### Amazon S3 Access
88
89
Opens ZIP files stored in Amazon S3 buckets.
90
91
```javascript { .api }
92
/**
93
* Opens a ZIP file from Amazon S3
94
* @param awsSdk - AWS SDK instance
95
* @param params - S3 parameters (Bucket, Key, etc.)
96
* @param options - Optional configuration object
97
* @returns Promise resolving to Directory object
98
*/
99
static async s3(awsSdk: any, params: S3Parameters, options?: OpenOptions): Promise<Directory>;
100
101
interface S3Parameters {
102
/** S3 bucket name */
103
Bucket: string;
104
/** S3 object key */
105
Key: string;
106
/** Optional version ID for versioned objects */
107
VersionId?: string;
108
/** Additional S3 parameters as per AWS SDK */
109
[key: string]: any;
110
}
111
```
112
113
**Usage Examples:**
114
115
```javascript
116
const AWS = require("aws-sdk");
117
const s3 = new AWS.S3();
118
119
// Open ZIP file from S3
120
const directory = await unzipper.Open.s3(s3, {
121
Bucket: "my-bucket",
122
Key: "archives/data.zip"
123
});
124
125
// Process S3-hosted ZIP contents
126
const manifest = directory.files.find(f => f.path === "manifest.json");
127
if (manifest) {
128
const manifestData = JSON.parse((await manifest.buffer()).toString());
129
console.log("Archive manifest:", manifestData);
130
}
131
132
// Extract multiple files from S3 ZIP
133
const imageFiles = directory.files.filter(f =>
134
f.type === "File" && /\.(jpg|png|gif)$/i.test(f.path)
135
);
136
137
for (const imageFile of imageFiles) {
138
const fileName = path.basename(imageFile.path);
139
imageFile.stream().pipe(fs.createWriteStream(`images/${fileName}`));
140
}
141
```
142
143
### Buffer Access
144
145
Opens ZIP files from in-memory buffers.
146
147
```javascript { .api }
148
/**
149
* Opens a ZIP file from a memory buffer
150
* @param buffer - Buffer containing ZIP file data
151
* @param options - Optional configuration object
152
* @returns Promise resolving to Directory object
153
*/
154
static async buffer(buffer: Buffer, options?: OpenOptions): Promise<Directory>;
155
```
156
157
**Usage Examples:**
158
159
```javascript
160
// Open ZIP from buffer (e.g., from database or API)
161
const zipBuffer = await loadZipFromDatabase();
162
const directory = await unzipper.Open.buffer(zipBuffer);
163
164
// Process in-memory ZIP
165
directory.files.forEach(async (file) => {
166
if (file.path.startsWith("config/")) {
167
const content = await file.buffer();
168
await processConfigFile(file.path, content);
169
}
170
});
171
172
// Convert buffer ZIP to file system
173
const tempFiles = directory.files.filter(f => f.type === "File");
174
for (const file of tempFiles) {
175
const outputPath = `temp/${file.path}`;
176
const outputDir = path.dirname(outputPath);
177
178
if (!fs.existsSync(outputDir)) {
179
fs.mkdirSync(outputDir, { recursive: true });
180
}
181
182
const content = await file.buffer();
183
fs.writeFileSync(outputPath, content);
184
}
185
```
186
187
### Custom Source Access
188
189
Opens ZIP files from custom source implementations.
190
191
```javascript { .api }
192
/**
193
* Opens a ZIP file from a custom source
194
* @param source - Custom source implementation
195
* @param options - Optional configuration object
196
* @returns Promise resolving to Directory object
197
*/
198
static async custom(source: any, options?: OpenOptions): Promise<Directory>;
199
```
200
201
## Directory Structure
202
203
The Directory object returned by Open methods provides access to the ZIP file contents.
204
205
```javascript { .api }
206
interface Directory {
207
/** Array of files and directories in the ZIP archive */
208
files: File[];
209
/** Extract all files to filesystem (if supported) */
210
extract(): Promise<void>;
211
}
212
213
interface File {
214
/** Path of the file/directory within the archive */
215
path: string;
216
/** Type of entry: 'File' or 'Directory' */
217
type: 'File' | 'Directory';
218
/** Creates a readable stream for the file content */
219
stream(): ReadableStream;
220
/** Returns the file content as a Buffer */
221
buffer(): Promise<Buffer>;
222
}
223
```
224
225
**Usage Examples:**
226
227
```javascript
228
const directory = await unzipper.Open.file("project.zip");
229
230
// Explore directory structure
231
console.log("Files in archive:");
232
directory.files
233
.filter(f => f.type === "File")
234
.forEach(f => console.log(` ${f.path}`));
235
236
console.log("Directories in archive:");
237
directory.files
238
.filter(f => f.type === "Directory")
239
.forEach(f => console.log(` ${f.path}/`));
240
241
// Extract entire archive (if supported)
242
await directory.extract();
243
244
// Work with specific files
245
const packageJson = directory.files.find(f => f.path === "package.json");
246
if (packageJson) {
247
// As buffer
248
const packageData = JSON.parse((await packageJson.buffer()).toString());
249
console.log(`Package: ${packageData.name}@${packageData.version}`);
250
251
// As stream
252
packageJson.stream().pipe(fs.createWriteStream("package.json"));
253
}
254
```
255
256
## Advanced Usage
257
258
### Archive Inspection
259
260
```javascript
261
const inspectArchive = async (zipPath) => {
262
const directory = await unzipper.Open.file(zipPath);
263
264
const stats = {
265
totalFiles: 0,
266
totalDirectories: 0,
267
totalSize: 0,
268
fileTypes: new Map(),
269
largestFile: null,
270
maxSize: 0
271
};
272
273
for (const file of directory.files) {
274
if (file.type === "File") {
275
stats.totalFiles++;
276
277
// Get file size by reading buffer
278
const buffer = await file.buffer();
279
const size = buffer.length;
280
stats.totalSize += size;
281
282
if (size > stats.maxSize) {
283
stats.maxSize = size;
284
stats.largestFile = file.path;
285
}
286
287
// Track file extensions
288
const ext = path.extname(file.path).toLowerCase();
289
stats.fileTypes.set(ext, (stats.fileTypes.get(ext) || 0) + 1);
290
} else {
291
stats.totalDirectories++;
292
}
293
}
294
295
return stats;
296
};
297
298
const stats = await inspectArchive("project.zip");
299
console.log(`Archive contains ${stats.totalFiles} files and ${stats.totalDirectories} directories`);
300
console.log(`Total size: ${stats.totalSize} bytes`);
301
console.log(`Largest file: ${stats.largestFile} (${stats.maxSize} bytes)`);
302
```
303
304
### Selective Processing
305
306
```javascript
307
const processArchiveByType = async (zipPath) => {
308
const directory = await unzipper.Open.file(zipPath);
309
310
const processors = {
311
'.json': async (file) => {
312
const content = JSON.parse((await file.buffer()).toString());
313
console.log(`JSON file ${file.path}:`, Object.keys(content));
314
},
315
316
'.txt': async (file) => {
317
const content = (await file.buffer()).toString();
318
console.log(`Text file ${file.path}: ${content.split('\n').length} lines`);
319
},
320
321
'.md': async (file) => {
322
const content = (await file.buffer()).toString();
323
const headings = content.match(/^#+\s+.+$/gm) || [];
324
console.log(`Markdown file ${file.path}: ${headings.length} headings`);
325
}
326
};
327
328
for (const file of directory.files) {
329
if (file.type === "File") {
330
const ext = path.extname(file.path).toLowerCase();
331
const processor = processors[ext];
332
333
if (processor) {
334
try {
335
await processor(file);
336
} catch (error) {
337
console.error(`Error processing ${file.path}:`, error.message);
338
}
339
}
340
}
341
}
342
};
343
344
await processArchiveByType("documentation.zip");
345
```
346
347
### Streaming Large Files
348
349
```javascript
350
const streamLargeFiles = async (zipPath, outputDir) => {
351
const directory = await unzipper.Open.file(zipPath);
352
353
// Find files larger than 1MB
354
const largeFiles = [];
355
for (const file of directory.files) {
356
if (file.type === "File") {
357
// For large files, avoid loading entire buffer
358
// Instead use stream processing
359
const stream = file.stream();
360
let size = 0;
361
362
await new Promise((resolve, reject) => {
363
stream.on('data', (chunk) => {
364
size += chunk.length;
365
});
366
stream.on('end', () => {
367
if (size > 1024 * 1024) { // 1MB
368
largeFiles.push({ file, size });
369
}
370
resolve();
371
});
372
stream.on('error', reject);
373
});
374
}
375
}
376
377
console.log(`Found ${largeFiles.length} large files`);
378
379
// Stream large files to disk
380
for (const { file, size } of largeFiles) {
381
console.log(`Streaming ${file.path} (${size} bytes)...`);
382
const outputPath = path.join(outputDir, file.path);
383
const outputDirPath = path.dirname(outputPath);
384
385
if (!fs.existsSync(outputDirPath)) {
386
fs.mkdirSync(outputDirPath, { recursive: true });
387
}
388
389
file.stream().pipe(fs.createWriteStream(outputPath));
390
}
391
};
392
393
await streamLargeFiles("large-archive.zip", "output");
394
```