Nodo JS – Transmite datos desde Busboy a AWS S3

Estoy tratando de cargar un archivo a s3 a través de ec2. Mi primer enfoque fue: subir el archivo a ec2 completamente y luego subir ese archivo a s3. Este enfoque no es bueno porque el tiempo de transferencia de ec2 a s3 es una pérdida de tiempo.

Actualmente estoy tratando de usar el flujo de carga de busboy para el flujo de carga de s3 para que el proceso de carga a ec2 y luego el de ec2 a s3 se realice de manera simultánea, ya que el flujo de soporte del método de carga de s3 como cuerpo de carga.

Aquí está mi código –

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); }); 

Tengo dudas, ¿está realmente subiendo a s3 simultáneamente como transmisión? ¿Hay algún inconveniente de este enfoque?

Para probar si la carga de transmisión multiparte de S3 está funcionando o no, tomé el registro de tiempo en tres puntos de ejecución:

  1. Antes de iniciar la carga desde el cliente ( uploadStartTime )
  2. Después de subir a EC2 ( busboyFinishTime )
  3. Después de transferido a S3 ( s3UploadFinishTime )

Entonces corro desde EC2. Después de cargar varios archivos de video (36.1 MB, 33.3 MB, 52.5 MB) observé que las partes se transfieren a S3 inmediatamente por cada 5MB (como lo definí) cargado en EC2. Cuando cargue partes en S3 verá un registro de la siguiente línea. Mostrará el progreso de carga de parte de archivo con el número de parte.

 console.log(evt); 

Para las tres subidas, busboyFinishTime y s3UploadFinishTime son iguales o apenas hay una diferencia de 1 segundo.

Ejemplo: cuando se cargan 52.5 MB

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

Código completo:

 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); }); 

De acuerdo con mis observaciones, confío en que esta es una de las mejores soluciones para cargar un archivo en S3 a través de EC2 utilizando una API REST implementada en EC2.

¿Estás intentando subir a S3 directamente desde el navegador? Si es así, puede utilizar el presigned-put para el navegador directo a las cargas S3.

Así es como se genera una URL PUT presignada usando minio-js

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

Ahora pasa esta URL presignada al cliente del navegador que puede usar XMLHttpRequest para PUTAR directamente un archivo a S3.