我正在尝试获取一个文件(从S3返回为Buffer
),解压缩它(这是一个流),然后将其保存到/tmp/foo
的磁盘。
如果我以异步方式处理untar(zlib.gunzip()
)函数,如果此脚本一次只能处理一个文件,它是否重要?使用流可以获得什么?
var getS3Args = { bucket: 'foo', key: 'bar.tar.gz' }
lib.getS3Object(getS3Args, function(getS3ObjectResponse) {
zlib.gunzip(getS3ObjectResponse.Body, function(err, result) {
if(err) return console.error(err);
// ?
console.log(result);
return callback(result);
});
});
答案 0 :(得分:3)
您可以直接从aws-sdk获取S3中的数据流。使用流时获得的优势是它使用的内存要少得多,因为它不需要在内存中使用整个缓冲区来对其进行操作。 Streams一次在小块上运行,然后这些块在处理完之后会被垃圾收集。使用您当前的方法,如果您想从S3下载1TB blob,您可能会遇到内存不足错误,因为您无法将整个缓冲区放入内存中。使用流时,您可能永远不会看到多于几MB的内存被使用,因为一个块将从HTTP响应中下来,然后该块将被解压缩,解压缩并自行写入您的文件系统而无需等待对于整个HTTP响应。
var AWS = require('aws-sdk')
var S3 = new AWS.S3()
var fs = require('fs')
var tar = require('tar')
var zlib = require('zlib')
var path = require('path')
var mkdirp = require('mkdirp')
var getS3Args = { bucket: 'foo', key: 'bar.tar.gz' }
var dest = '/path/to/destination'
S3.getObject(getS3Args)
.createReadStream()
.pipe(zlib.Unzip())
.pipe(tar.Parse())
.on('entry', function(entry) {
var isDir = 'Directory' === entry.type
var fullpath = path.join(dest, entry.path)
var directory = isDir ? fullpath : path.dirname(fullpath)
mkdirp(directory, function(err) {
if (err) throw err
if (!isDir) entry.pipe(fs.createWriteStream(fullpath))
})
})