node-unzipper
node-unzipper copied to clipboard
Feature request: support for `aws-sdk` v3
The S3 client for v3 of the SDK signature has changed when trying to create a read stream.
The signature has changed so that instead of https://github.com/ZJONSSON/node-unzipper/blob/7f83183d4475abeaaa9251d3511c840647bca788/lib/Open/index.js#L86-L92, it would have to look something like
stream: function(offset,length) {
var d = {};
for (var key in params)
d[key] = params[key];
d.Range = 'bytes='+offset+'-' + (length ? length : '');
return new Promise(function(resolve,reject) {
client.getObject(d, function(err, data) {
if (err)
reject(err);
else
resolve(data.Body);
});
});
}
, although it's unclear how to distinguish between a v2 client and a v3 client and if the caller would be happy with a Promise being returned instead of the stream directly.
If a v3 client is passed in, the following error is thrown in the current version of unzipper:
ERROR TypeError: client.getObject(...).createReadStream is not a function
Any updates on this issue?
AFAIK the getObject method of SDK v3 does not support the 'synchronous' way of creating stream; the response.Body is available asynchronously (via callback/promise). Should the support will be implemented, some refactoring of existing code will be required. This may involve some breaking changes, unfortunately, with node v8.
CMIIW, the SDK v3 also bumps the minimum supported node version to v10
I have created PR https://github.com/ZJONSSON/node-unzipper/pull/277. Please check if any changes are required.
Suggestions for test scripts are welcome, since I have yet to figure out how to implement one.
Workaround I did that worked:
const directory = await unzipper.Open.custom({
async size() {
const info = await s3.send(
new HeadObjectCommand({
Bucket: bucket,
Key: key,
}),
);
return info.ContentLength;
},
stream(offset, length) {
const stream = new PassThrough();
s3.send(
new GetObjectCommand({
Bucket: bucket,
Key: key,
Range: `bytes=${offset}-${length ?? ""}`,
}),
)
.then((response) => {
response.Body.pipe(stream);
})
.catch((error) => {
stream.emit("error", error);
});
return stream;
},
});