[nodejs] S3 내의 파일을 zip 압축하기
S3 내의 파일을 로컬에 다운로드하지 않고 zip 파일로 압축하는 기능이다. 기본 개념은 아래의 이미지와 같다고 한다.
이미지만 봐서는 이번에도 역시 리모트의 파일을 S3에 다운로드하는 것과 같이 stream
을 사용하는 것 같다. 자 이제 코드를.. 뭘 더 설명해야할지 모르니까.. 코드를 보도록 하자.
const env = require("./env.js");
const AWS = require("aws-sdk");
const stream = require("stream");
const archiver = require('archiver');
const moment = require("moment");
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
region: process.env.AWS_REGION
});
async function zip(keys, name)
{
console.log("[" + moment().format('YYYY-MM-DD HH:mm:ss') + "] " + name + " compressing start");
const s3FileDwnldStreams = keys.map(key => {
const stream = s3.getObject({ Bucket: process.env.AWS_BUCKET, Key: key }).createReadStream();
return {
stream,
fileName: key,
}
});
const streamPassThrough = new stream.PassThrough();
const uploadParams = {
ACL: "public-read",
Body: streamPassThrough,
ContentType: "application/zip",
Bucket: process.env.AWS_BUCKET,
Key: process.env.AWS_BUCKET_DIR + "/" + name,
};
const s3Upload = () => {
return {
writeStream: streamPassThrough,
promise: s3.upload(uploadParams).promise()
};
}
const archive = archiver("zip", {
zlib: { level: 9 },
});
archive.on("error", error => {
throw new Error(
`${error.name} ${error.code} ${error.message} ${error.path} ${error.stack}`
)
});
const {writeStream, promise} = s3Upload();
return new Promise(async (resolve, reject) => {
archive.pipe(writeStream);
s3FileDwnldStreams.forEach(s3FileDwnldStream => {
archive.append(s3FileDwnldStream.stream, {
name: s3FileDwnldStream.fileName,
})
});
archive.finalize();
await promise;
promise.then(() => {
resolve(promise);
}).catch((err) => {
reject(err.message);
});
}).catch(error => {
throw new Error(`${error.code} ${error.message} ${error.data}`)
})
}
실행은 아래와 같은 데이터를 넘겨주면 된다.
const keys = ["dir/file1.txt", "dir/file2.txt", "dir/file3.txt"];
const name = "txt.zip";
zip(keys, name);
실행하면 S3 버킷 내 dir/txt.zip
파일이 생성된다. 로컬에 다운로드해서 처리하면 좀 더 편할 수도 있는데.. 이게 lambda 에서 실행될 수 있어야 하기 때문에 이런 식으로 처리를 하게 됐다.