节点上的路由获取一个zip文件,然后从那里将其解压缩到内存中并将其上传到S3存储桶。一切工作正常,但是在zip文件中的所有文件都处理完后,我正在努力解决。
function unzipAndUploadToS3(fileInfo) {
return new Promise((resolve, reject) => {
fs.createReadStream(fileInfo.zip.path)
.pipe(unzipper.Parse())
.pipe(etl.map(entry => {
if (checkEntry(entry.path)) {
fileInfo.name = entry.path;
entry
.buffer()
.then(content => {
fileInfo.data = content;
AWS.uploadToS3(fileInfo).then(result => {
console.log(result.Location);
resolve(result.Location); //ALWAYS Resolves here
}).catch(err => {
console.error(err);
reject(err);
})
})
}
else
entry.autodrain();
}))
});
}
我已经尝试过Promise.all和Async / Await,但似乎可以绕开它。
答案 0 :(得分:1)
我以前从未使用过NullPointerException
,但是他们的documentation上有一条注释
从流切换到承诺链...
然后给出代码etl
。您说您尝试过.promise().then(...)
,但是您没有说如何,所以我不知道您是否已经尝试过。但这是我认为事情可能会发展的方向:
Promise.all
尽管所有的Promise必须正确地链接在一起以进行条目缓冲,然后才能上载到s3,但此方法才能起作用。我标记了重要的回报,以保持带有评论的链接。
对我来说,还有一些其他问题:我不敢相信您可以继续将相同的function unzipAndUploadToS3(fileInfo) {
return new Promise((resolve, reject) => {
fs.createReadStream(fileInfo.zip.path)
.pipe(unzipper.Parse())
.pipe(etl.map(entry => {
if (checkEntry(entry.path)) {
fileInfo.name = entry.path;
return entry.buffer() //<- return promise
.then(content => {
fileInfo.data = content;
return AWS.uploadToS3(fileInfo) //<- return promise
})
}
else
entry.autodrain();
}))
.promise().then(awsPromises => Promise.all(awsPromises)) //<- return promise
.then(x => resolve('x should be an array of s3 results'))
.catch(err => reject(err));
});
}
与多个文件重复使用。在我看来,这是一个竞争条件:上一个上传是否会在下一个文件覆盖fileInfo
和fileInfo.data
之前完成?我的猜测是,最好在地图内部创建一个新的fileInfo对象,而不是对zip中的所有文件重复使用相同的对象。
答案 1 :(得分:0)
这就是最终为我工作的原因。这会使用unziper,etl和lodash。
function unzipAndUploadToS3(fileInfo) {
return new Promise((resolve, reject) => {
var filesToProcess = [];
var filesStream = fs.createReadStream(fileInfo.zip.path)
.pipe(unzipper.Parse())
.pipe(etl.map(entry => {
if (checkEntry(entry.path)) {
fileInfo.name = entry.path.substr(entry.path.indexOf('/') + 1, entry.path.length);
entry
.buffer()
.then(content => {
fileInfo.data = content;
var newObj = _.clone(fileInfo); //need to clone object because of object reference in assignment
var promise = new Promise(function(resolve, reject) { //create new promise to upload to S3
AWS.uploadToS3(newObj).then(result => { //a function in another module uses aws-sdk
resolve(result)
}).catch(err => reject(err));
})
filesToProcess.push(promise); //push this promise into an array of promises
})
}
else
entry.autodrain();
}))
filesStream.on('readable', function () { console.log('readable'); })
.on('data', function (data) { console.log('data', data); })
.on('error', function (err) {
console.error('Error', err);
reject(err);
})
.on('end', function () {
Promise.all(filesToProcess).then(values => { //process all the promises
console.log("values>", values);
resolve(values);
}).catch(err => {reject(err)});
})
});
}