S3バケットにある選択したファイル(ビデオと画像)で構成されるZipファイルを作成する必要があります。
以下のコードを使用している現時点での問題は、Lambdaのメモリ制限にすぐに達してしまうことです。
async.eachLimit(files, 10, function(file, next) {
var params = {
Bucket: bucket, // bucket name
Key: file.key
};
s3.getObject(params, function(err, data) {
if (err) {
console.log('file', file.key);
console.log('get image files err',err, err.stack); // an error occurred
} else {
console.log('file', file.key);
Zip.file(file.key, data.Body);
next();
}
});
},
function(err) {
if (err) {
console.log('err', err);
} else {
console.log('Zip', Zip);
content = Zip.generateNodeStream({
type: 'nodebuffer',
streamFiles:true
});
var params = {
Bucket: bucket, // name of dest bucket
Key: 'zipped/images.Zip',
Body: content
};
s3.upload(params, function(err, data) {
if (err) {
console.log('upload Zip to s3 err',err, err.stack); // an error occurred
} else {
console.log(data); // successful response
}
});
}
});
これはLambdaを使用して可能ですか、または別のアプローチを検討する必要がありますか?
オンザフライで圧縮されたZipファイルに書き込むことができるため、メモリの問題が多少解消されますか、それとも圧縮前にファイルを収集する必要がありますか?
どんな助けでも大歓迎です。
さて、私はこれを今日行う必要があり、それは機能します。ストリームへのダイレクトバッファー。ディスクは含まれません。したがって、メモリやディスクの制限はここでは問題になりません:
'use strict';
const AWS = require("aws-sdk");
AWS.config.update( { region: "eu-west-1" } );
const s3 = new AWS.S3( { apiVersion: '2006-03-01'} );
const _archiver = require('archiver');
//This returns us a stream.. consider it as a real pipe sending fluid to S3 bucket.. Don't forget it
const streamTo = (_bucket, _key) => {
var stream = require('stream');
var _pass = new stream.PassThrough();
s3.upload( { Bucket: _bucket, Key: _key, Body: _pass }, (_err, _data) => { /*...Handle Errors Here*/ } );
return _pass;
};
exports.handler = async (_req, _ctx, _cb) => {
var _keys = ['list of your file keys in s3'];
var _list = await Promise.all(_keys.map(_key => new Promise((_resolve, _reject) => {
s3.getObject({Bucket:'bucket-name', Key:_key})
.then(_data => _resolve( { data: _data.Body, name: `${_key.split('/').pop()}` } ));
}
))).catch(_err => { throw new Error(_err) } );
await new Promise((_resolve, _reject) => {
var _myStream = streamTo('bucket-name', 'fileName.Zip'); //Now we instantiate that pipe...
var _archive = _archiver('Zip');
_archive.on('error', err => { throw new Error(err); } );
//Your promise gets resolved when the fluid stops running... so that's when you get to close and resolve
_myStream.on('close', _resolve);
_myStream.on('end', _resolve);
_myStream.on('error', _reject);
_archive.pipe(_myStream); //Pass that pipe to _archive so it can Push the fluid straigh down to S3 bucket
_list.forEach(_itm => _archive.append(_itm.data, { name: _itm.name } ) ); //And then we start adding files to it
_archive.finalize(); //Tell is, that's all we want to add. Then when it finishes, the promise will resolve in one of those events up there
}).catch(_err => { throw new Error(_err) } );
_cb(null, { } ); //Handle response back to server
};
複数のストリームをオブジェクトにパイプする方法がわからないので、ストリームの使用は難しいかもしれません。標準のファイルオブジェクトを使用してこれを数回実行しました。これは多段階のプロセスであり、非常に高速です。 LambdaはLinuxで動作するため、システムの/ tmpディレクトリを含むすべてのLinuxリソースが手元にあることに注意してください。