diff --git a/README.md b/README.md index 74e04f2..0436cda 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,41 @@ async function main() { main(); ``` +### Open.custom(source, [options]) +This function can be used to provide a custom source implementation. The source parameter expects a `stream` and a `size` function to be implemented. The size function should return a `Promise` that resolves the total size of the file. The stream function should return a `Readable` stream according to the supplied offset and length parameters. + +Example: + +```js +// Custom source implementation for reading a zip file from Google Cloud Storage +const { Storage } = require('@google-cloud/storage'); + +async function main() { + const storage = new Storage(); + const bucket = storage.bucket('my-bucket'); + const zipFile = bucket.file('my-zip-file.zip'); + + const customSource = { + stream: function(offset, length) { + return zipFile.createReadStream({ + start: offset, + end: length && offset + length + }) + }, + size: async function() { + const objMetadata = (await zipFile.getMetadata())[0]; + return objMetadata.size; + } + }; + + const directory = await unzipper.Open.custom(customSource); + console.log('directory', directory); + // ... +} + +main(); +``` + ### Open.[method].extract() The directory object returned from `Open.[method]` provides an `extract` method which extracts all the files to a specified `path`, with an optional `concurrency` (default: 1). diff --git a/lib/Open/index.js b/lib/Open/index.js index f6c4068..fd89746 100644 --- a/lib/Open/index.js +++ b/lib/Open/index.js @@ -92,6 +92,10 @@ module.exports = { } }; + return directory(source, options); + }, + + custom: function(source, options) { return directory(source, options); } }; diff --git a/test/openCustom.js b/test/openCustom.js new file mode 100644 index 0000000..5cd0f78 --- /dev/null +++ b/test/openCustom.js @@ -0,0 +1,41 @@ +'use strict'; + +var test = require('tap').test; +var fs = require('fs'); +var path = require('path'); +var unzip = require('../unzip'); +var Promise = require('bluebird'); + +test("get content of a single file entry out of a zip", function (t) { + var archive = path.join(__dirname, '../testData/compressed-standard/archive.zip'); + + var customSource = { + stream: function(offset,length) { + return fs.createReadStream(archive, {start: offset, end: length && offset+length}); + }, + size: function() { + return new Promise(function(resolve, reject) { + fs.stat(archive, function(err, d) { + if (err) + reject(err); + else + resolve(d.size); + }); + }); + } + }; + + return unzip.Open.custom(customSource) + .then(function(d) { + var file = d.files.filter(function(file) { + return file.path == 'file.txt'; + })[0]; + + return file.buffer() + .then(function(str) { + var fileStr = fs.readFileSync(path.join(__dirname, '../testData/compressed-standard/inflated/file.txt'), 'utf8'); + t.equal(str.toString(), fileStr); + t.end(); + }); + }); +}); \ No newline at end of file