节点JS – 将数据从Busboystream式传输到AWS S3

我想通过ec2上传一个文件到s3。 我的第一个方法是 – 将文件完全上传到ec2,然后将该file upload到s3。 这种方法并不好,因为从ec2到s3的传输时间浪费时间。

目前我正尝试使用busboy上传stream上传s3stream,以便上传到ec2,然后ec3到s3将同时完成,因为s3 “upload”方法支持stream上传Body。

这是我的代码 –

router.post('/s3StreamUpload', function(req, res, next) { var busboy = new Busboy({headers: req.headers}); busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { console.log('Before Upload: ' + new Date()); console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype); var s3 = new AWS.S3({ params: {Bucket: 'sswa', Key: filename, Body: file}, options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB }); s3.upload().on('httpUploadProgress', function (evt) { console.log(evt); }).send(function (err, data) { console.log('After Upload: ' + new Date()); console.log(err, data); }); }); busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) { console.log('Field [' + fieldname + ']: value: ' + inspect(val)); }); busboy.on('finish', function() { console.log('Done parsing form!'); res.writeHead(303, { Connection: 'close', Location: '/' }); res.end(); }); req.pipe(busboy); }); 

我怀疑它是否真的上传到s3作为stream? 这种方法有什么缺点吗?

为了testing多部分stream媒体上传到S3是否工作,我花了三个时间点执行日志 –

  1. 在开始从客户端上传之前( uploadStartTime
  2. 上传到EC2( busboyFinishTime
  3. 转入S3( s3UploadFinishTime )后

然后我从EC2跑。 上传不同长度的video文件(36.1 MB,33.3 MB,52.5 MB)后,我观察到部件被立即传输到S3,每个5MB(按照我的定义)上传到EC2。 上传部件到S3时,您会看到以下行的日志。 它将显示部分上传进度与零件号码。

 console.log(evt); 

对于所有三个上传busboyFinishTimes3UploadFinishTime是相同的或几乎没有1秒的差异。

例如:上传52.5 MB时

 { "uploadStartTime": "2016-04-28T14:19:51.365Z", "busboyFinishTime": "2016-04-28T14:22:26.292Z", "s3UploadFinishTime": "2016-04-28T14:22:26.558Z" } 

全码:

 router.post('/s3StreamUpload', function(req, res, next) { var busboy = new Busboy({headers: req.headers}); var uploadStartTime = new Date(), busboyFinishTime = null, s3UploadFinishTime = null; busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype); var s3 = new AWS.S3({ params: {Bucket: 'sswa', Key: filename, Body: file}, options: {partSize: 5 * 1024 * 1024, queueSize: 10} // 5 MB }); s3.upload().on('httpUploadProgress', function (evt) { console.log(evt); }).send(function (err, data) { s3UploadFinishTime = new Date(); if(busboyFinishTime && s3UploadFinishTime) { res.json({ uploadStartTime: uploadStartTime, busboyFinishTime: busboyFinishTime, s3UploadFinishTime: s3UploadFinishTime }); } console.log(err, data); }); }); busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) { console.log('Field [' + fieldname + ']: value: ' + inspect(val)); }); busboy.on('finish', function() { console.log('Done parsing form!'); busboyFinishTime = new Date(); if(busboyFinishTime && s3UploadFinishTime) { res.json({ uploadStartTime: uploadStartTime, busboyFinishTime: busboyFinishTime, s3UploadFinishTime: s3UploadFinishTime }); } }); req.pipe(busboy); }); 

根据我的观察,我感到有信心,这是最好的方式,通过使用部署在EC2上的REST API,通过EC2将file upload到S3

你想直接从浏览器上传到S3吗? 如果是这样你可以使用presigned-put直接浏览器上传S3。

这是你如何使用minio-js生成一个预先指定的PUTurl

 s3Client.presignedPutObject('my-bucketname', 'my-objectname', 1000, function(e, presignedUrl) { if (e) return console.log(e) console.log(presignedUrl) }) 

现在您将这个预先设定的URL传递给浏览器客户端,它可以使用XMLHttpRequest直接将文件传送到S3。