Skip to content

Commit 3142fd5

Browse files
committed
Implemented needed code to extract zip archives into a directory
1 parent e989cf1 commit 3142fd5

File tree

1 file changed

+54
-6
lines changed

1 file changed

+54
-6
lines changed

lib/wrappers/file-system.ts

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
11
import * as fs from "fs";
2-
import { Extract } from "unzip";
2+
import * as path from "path";
3+
import * as yauzl from "yauzl";
4+
import * as util from "util";
5+
6+
const access = util.promisify(fs.access);
7+
const mkdir = util.promisify(fs.mkdir);
38

49
export class FileSystem {
510
public exists(path: string): boolean {
611
return fs.existsSync(path);
712
}
813

914
public extractZip(pathToZip: string, outputDir: string): Promise<void> {
10-
return new Promise<void>((resolve, reject) => {
11-
const stream = fs.createReadStream(pathToZip).pipe(Extract({ path: outputDir }));
12-
stream.on("close", resolve);
13-
stream.on("error", reject);
14-
});
15+
return new Promise((resolve, reject) => {
16+
yauzl.open(pathToZip, { autoClose: true, lazyEntries: true }, (e, zipFile) => {
17+
if (e) return reject(e);
18+
19+
zipFile.on('entry', entry => {
20+
const fn = <string>entry.fileName;
21+
if (/\/$/.test(fn)) {
22+
return zipFile.readEntry();
23+
}
24+
25+
zipFile.openReadStream(entry, (err, stream) => {
26+
if(err) return reject(err);
27+
28+
const filePath = `${outputDir}/${fn}`;
29+
30+
return createParentDirsIfNeeded(filePath)
31+
.catch(e => reject(e))
32+
.then(() => {
33+
const outfile = createOutfile(filePath);
34+
stream.once('end', () => {
35+
zipFile.readEntry();
36+
outfile.close();
37+
});
38+
stream.pipe(outfile);
39+
});
40+
});
41+
});
42+
43+
zipFile.once('end', () => resolve());
44+
45+
zipFile.readEntry();
46+
});
47+
})
1548
}
1649

1750
public readDirectory(path: string): string[] {
@@ -23,3 +56,18 @@ export class FileSystem {
2356
return JSON.parse(content.toString());
2457
}
2558
}
59+
60+
function createParentDirsIfNeeded(filePath: string) {
61+
const dirs = path.dirname(filePath).split(path.sep);
62+
return dirs.reduce((p, dir, index) => p.then(parent => {
63+
const current = `${parent}${path.sep}${dir}`;
64+
65+
return access(current)
66+
.catch(e => mkdir(current))
67+
.then(() => current);
68+
}), Promise.resolve(''));
69+
}
70+
71+
function createOutfile(path: string): fs.WriteStream {
72+
return fs.createWriteStream(path);
73+
}

0 commit comments

Comments
 (0)