2016-09-11 2 views
2

파일을 가져 와서 (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); 
    }); 
}); 

답변

3

S3의 데이터 스트림은 aws-sdk에서 직접 가져올 수 있습니다. 스트림을 사용할 때 얻을 수있는 장점은 메모리에서 전체 버퍼를 조작 할 필요가 없기 때문에 훨씬 적은 메모리를 사용한다는 것입니다. 스트림은 한 번에 작은 덩어리에서 작동하고 그 덩어리는 처리 된 후에 가비지 수집됩니다. 현재의 방법을 사용하면 S3에서 1TB BLOB를 다운로드하려는 경우 전체 버퍼를 메모리에 저장할 수있는 방법이 없기 때문에 메모리 부족 오류가 발생할 가능성이 높습니다. 스트림을 사용할 때, HTTP 응답에서 청크가 나올 것이고, 그 청크가 압축을 풀고, untar하고, 파일 시스템에 기다릴 필요없이 쓰게 될 것이기 때문에 사용되는 메모리가 몇 MB가 넘는 것을 보지 못할 것입니다 전체 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)) 
    }) 
    }) 
관련 문제