UNPKG

r2-utils-js

Version:

Readium 2 'utils' for NodeJS (TypeScript)

295 lines 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Zip2 = void 0; const tslib_1 = require("tslib"); const debug_ = require("debug"); const request = require("request"); const requestPromise = require("request-promise-native"); const yauzl = require("yauzl"); const UrlUtils_1 = require("../http/UrlUtils"); const BufferUtils_1 = require("../stream/BufferUtils"); const zip_1 = require("./zip"); const zip2RandomAccessReader_Http_1 = require("./zip2RandomAccessReader_Http"); const debug = debug_("r2:utils#zip/zip2"); class Zip2 extends zip_1.Zip { static loadPromise(filePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if ((0, UrlUtils_1.isHTTP)(filePath)) { return Zip2.loadPromiseHTTP(filePath); } return new Promise((resolve, reject) => { yauzl.open(filePath, { lazyEntries: true, autoClose: false }, (err, zip) => { if (err || !zip) { debug("yauzl init ERROR"); debug(err); reject(err); return; } const zip2 = new Zip2(filePath, zip); zip.on("error", (erro) => { debug("yauzl ERROR"); debug(erro); reject(erro); }); zip.readEntry(); zip.on("entry", (entry) => { if (entry.fileName[entry.fileName.length - 1] === "/") { } else { zip2.addEntry(entry); } zip.readEntry(); }); zip.on("end", () => { debug("yauzl END"); resolve(zip2); }); zip.on("close", () => { debug("yauzl CLOSE"); }); }); }); }); } static loadPromiseHTTP(filePath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const needsStreamingResponse = true; return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () { const failure = (err) => { debug(err); reject(err); }; const success = (res) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) { failure("HTTP CODE " + res.statusCode); return; } debug(filePath); debug(res.headers); if (!res.headers["content-length"]) { reject("content-length not supported!"); return; } const httpZipByteLength = parseInt(res.headers["content-length"], 10); debug(`Content-Length: ${httpZipByteLength}`); if (!res.headers["accept-ranges"] || res.headers["accept-ranges"].indexOf("bytes") < 0) { if (httpZipByteLength > (2 * 1024 * 1024)) { reject("accept-ranges not supported, file too big to download: " + httpZipByteLength); return; } debug("Downloading: " + filePath); const failure_ = (err) => { debug(err); reject(err); }; const success_ = (ress) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (ress.statusCode && (ress.statusCode < 200 || ress.statusCode >= 300)) { failure_("HTTP CODE " + ress.statusCode); return; } let buffer; try { buffer = yield (0, BufferUtils_1.streamToBufferPromise)(ress); } catch (err) { debug(err); reject(err); return; } yauzl.fromBuffer(buffer, { lazyEntries: true }, (err, zip) => { if (err || !zip) { debug("yauzl init ERROR"); debug(err); reject(err); return; } const zip2 = new Zip2(filePath, zip); zip.on("error", (erro) => { debug("yauzl ERROR"); debug(erro); reject(erro); }); zip.readEntry(); zip.on("entry", (entry) => { if (entry.fileName[entry.fileName.length - 1] === "/") { } else { zip2.addEntry(entry); } zip.readEntry(); }); zip.on("end", () => { debug("yauzl END"); resolve(zip2); }); zip.on("close", () => { debug("yauzl CLOSE"); }); }); }); if (needsStreamingResponse) { request.get({ headers: {}, method: "GET", uri: filePath, }) .on("response", (res) => tslib_1.__awaiter(this, void 0, void 0, function* () { try { yield success_(res); } catch (successError) { failure_(successError); return; } })) .on("error", failure_); } else { let ress; try { ress = yield requestPromise({ headers: {}, method: "GET", resolveWithFullResponse: true, uri: filePath, }); } catch (err) { failure_(err); return; } yield success_(ress); } return; } const httpZipReader = new zip2RandomAccessReader_Http_1.HttpZipReader(filePath, httpZipByteLength); yauzl.fromRandomAccessReader(httpZipReader, httpZipByteLength, { lazyEntries: true, autoClose: false }, (err, zip) => { if (err || !zip) { debug("yauzl init ERROR"); debug(err); reject(err); return; } zip.httpZipReader = httpZipReader; const zip2 = new Zip2(filePath, zip); zip.on("error", (erro) => { debug("yauzl ERROR"); debug(erro); reject(erro); }); zip.readEntry(); zip.on("entry", (entry) => { if (entry.fileName[entry.fileName.length - 1] === "/") { } else { zip2.addEntry(entry); } zip.readEntry(); }); zip.on("end", () => { debug("yauzl END"); resolve(zip2); }); zip.on("close", () => { debug("yauzl CLOSE"); }); }); }); if (needsStreamingResponse) { request.get({ headers: {}, method: "HEAD", uri: filePath, }) .on("response", (res) => tslib_1.__awaiter(this, void 0, void 0, function* () { try { yield success(res); } catch (successError) { failure(successError); return; } })) .on("error", failure); } else { let res; try { res = yield requestPromise({ headers: {}, method: "HEAD", resolveWithFullResponse: true, uri: filePath, }); } catch (err) { failure(err); return; } yield success(res); } })); }); } constructor(filePath, zip) { super(); this.filePath = filePath; this.zip = zip; this.entries = {}; } freeDestroy() { debug("freeDestroy: Zip2 -- " + this.filePath); if (this.zip) { this.zip.close(); } } entriesCount() { return this.zip.entryCount; } hasEntries() { return this.entriesCount() > 0; } hasEntry(entryPath) { return this.hasEntries() && this.entries[entryPath]; } getEntries() { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!this.hasEntries()) { return Promise.resolve([]); } return Promise.resolve(Object.keys(this.entries)); }); } entryStreamPromise(entryPath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!this.hasEntries() || !this.hasEntry(entryPath)) { return Promise.reject("no such path in zip: " + entryPath); } const entry = this.entries[entryPath]; return new Promise((resolve, reject) => { this.zip.openReadStream(entry, (err, stream) => { if (err) { debug("yauzl openReadStream ERROR"); debug(err); reject(err); return; } const streamAndLength = { length: entry.uncompressedSize, reset: () => tslib_1.__awaiter(this, void 0, void 0, function* () { return this.entryStreamPromise(entryPath); }), stream, }; resolve(streamAndLength); }); }); }); } addEntry(entry) { this.entries[entry.fileName] = entry; } } exports.Zip2 = Zip2; //# sourceMappingURL=zip2.js.map