我应该如何批量上传到s3,并通过最终callback从nodeJS webserver插入到MongoDB?
我有一个Web服务器,接受来自客户端的图像,处理它们,将它们上传到S3,批量插入到我的mongoDB,最后发送到客户端的JSON结果。
使用单个图像的工作如下:
router.post("/upload", function(req, res){ var form = new multiparty.Form(); form.parse(req,function(err,fields,files){ s3.upload({ Key: filename, Bucket: bucketname, ACL: "public-read", Body: fs.createReadStream(filepath) }, function(err, data){ if(err) //error handle Model.collection.insert({"name": "name", "url" : data.Location}, function(err, result){ if(err) //error handle res.json({result: result}) }) }) }) })
这工作得很好,因为我简单地上传文件数据到s3 – >完成后,插入s3的输出(url)到数据库 – >完成后,将mongo的结果作为jsonarray发送到客户端。
问题是 – 我的客户端HTML除了多个type=file
input相同的name=images
,以便我可以在我的表单parsing器中访问它们作为images[i]
。 上述algorithm重复images.length
次。 当我不得不等待所有的asynchronousS3上传 – > mongo插入完成,我不得不把这个jsonarray结果返回给客户端时,问题会上升,我不能确定这个工作的callback方式和方式。
我试过的是以下几点:
- 遍历图像,首先将它们上传到S3,用生成的url(
[data.Location]
)填充数组。 批量插入到mongoDB,并在callback中将jsonarray结果返回给客户端。 这是因为mongo插入不等待S3上传不起作用。 - 迭代通过图像,上传和插入图像到S3和mongoDB每次迭代。
if (currentIndex = images.length)
,则返回jsonarray结果。 这不能准确地工作,因为我不知道哪些图像将最后结束(不同的大小)。
我应该如何devisealgorithm批量上传s3,批量插入到mongo,返回结果包括S3 URL,文件名等回到客户端作为jsonarray?
提前致谢!
我通常用Promises来解决这类问题,参见: Bluebird 。
然后你可以使用Promise.all()
在S3上进行批量上传,一旦你得到callback,你可以批量插入到Mongo中,完成后,运行最后一个callback。 或者,你可以做一个批处理,做两件事: upload->insert to mongo
,当所有这些都完成后,返回最后的callback。 这将取决于您的服务器和一次上传多less个文件。 您也可以使用Promise.map()
, concurrency
选项设置为您要运行的任何并发任务。
伪代码示例:
让asume getFiles
, uploadFile
和uploadToMongo
返回一个Promise
对象。
var maxConcurrency = 10; getFiles() .map(function(file){ return uploadFile(file) .then(uploadToMongo) },{concurrency: maxConcurrency}) .then(function(){ return finalCallback(); }).catch(handleError);
例如,如何手动 “promisify * S3:
function uploadMyFile(filename, filepath, bucketname) { return new Promise(function(resolve, reject){ s3.upload({ Key: filename, Bucket: bucketname, ACL: "public-read", Body: fs.createReadStream(filepath) }, function(err, data){ //This err will get to the "catch" statement. if (err) return reject(err); // Handle success and eventually call: return resolve(data); }); }); }
你可以使用这个:
uploadMyFile .then(handleSuccess) .catch(handleFailure);
所有漂亮和漂亮!
如果你不能承诺工作,你可以将你的通话状态存储在一个局部variables中。 您只需将呼叫分成两个function,一个上传和一个批量上传。
这是肮脏的代码,但你应该能够得到这个想法:
router.post("/upload", function(req, res){ var form = new multiparty.Form(); form.parse(req,function(err,fields,files){ if (err){ cb(err); } else { bulkUpload(files, fields, function(err, result){ if (err){ cb(err); } else { res.json({result:result}); } }) } }) }) function singleUpload(file, field, cb){ s3.upload({ Key: filename, Bucket: bucketname, ACL: "public-read", Body: fs.createReadStream(filepath) }, function(err, data){ if(err) cb(err); } else { Model.collection.insert({"name": "name", "url" : data.Location}, function(err, result){ if(err){ cb(err); } else { cb(null, result); } }) } }) } function bulkUpload (files, fields, cb) { var count = files.length; var successes = 0; var errors = 0; for (i=0;i<files.length;i++) { singleUpload(files[i], fields[i], function (err, res) { if (err) { errors++ //do something with the error? } else { successes++ //do something with the result? } //when you have worked through all of the files, call the final callback if ((successes + errors) >= count) { cb( null, { successes:successes, errors:errors } ) } }); } }
这不会是我推荐的方法,但另一个用户已经提出了承诺。 我认为一种替代方法会更有帮助。
祝你好运!
- 如何确定对象是否存在AWS S3 Node.JS sdk
- S3.getSignedUrl接受多个内容types
- 使用Connect Multiparty,Jimp和Amazon s3fs节点模块将resize的照片上传到Amazon s3
- AWS nodejs microservice:在S3存储桶中的文件发生更改时迭代调用服务
- NodeJS AWS S3代理有时会挂起 – 重新启动帮助
- 我应该在哪里存储我的Node.js应用程序的密钥?
- 使用Lambda节点从S3上的文件创buildS3上的zip文件
- 如何通过webapp上传一个一兆字节的文件到Amazon S3?
- 从Amazon S3直接将文件stream式传输到客户端(Node.js)