S3file uploadstream使用节点js

我试图find一些解决scheme,使用节点js服务器与要求在亚马逊S3上stream文件:

  • 不要将临时文件存储在服务器或内存中。 但是最新的一些限制不完整的文件,缓冲可以用于上传。
  • 上传的文件大小没有限制。
  • 不要冻结服务器,直到完成file upload,因为在繁重的file upload的情况下,其他请求的等待时间会意外增加。

我不想使用从浏览器直接上传文件,因为在这种情况下需要共享S3证书。 从js服务器上传文件的另外一个原因是在上传文件之前可能还需要申请一些authentication。

我试图用节点多方来实现这一点。 但这并不像预期的那样工作。 你可以在https://github.com/andrewrk/node-multiparty/issues/49看到我的解决scheme和问题。 它适用于小文件,但大小为15MB的文件失败。

任何解决scheme或替代?

您现在可以使用正式的Amazon SDK for nodejs进行stream式传输,甚至更棒,您最终可以在事先不知道文件大小的情况下执行此操作 ,只需将该stream作为正文传递即可:

 var fs = require('fs'); var zlib = require('zlib'); var body = fs.createReadStream('bigfile').pipe(zlib.createGzip()); var s3obj = new AWS.S3({params: {Bucket: 'myBucket', Key: 'myKey'}}); s3obj.upload({Body: body}) .on('httpUploadProgress', function(evt) { console.log(evt); }) .send(function(err, data) { console.log(err, data) }); 

https://www.npmjs.org/package/streaming-s3一个尝试。

我用它来并行上传几个大文件(> 500Mb),并且工作得很好。 它非常易于configuration,并允许您跟踪上传统计信息。 您不需要知道对象的总大小,也不会在磁盘上写入任何内容。

我在这里使用s3-upload-stream模块在一个工作项目中。

他的http-framework存储库中还有一些来自@raynos的好例子。

或者,你可以看看 – https://github.com/minio/minio-js 。 它具有最less的抽象API实现最常用的S3调用。

这里是一个stream式上传的例子。

 $ npm install minio $ cat >> put-object.js << EOF var Minio = require('minio') var fs = require('fs') // find out your s3 end point here: // http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region var s3Client = new Minio({ url: 'https://<your-s3-endpoint>', accessKey: 'YOUR-ACCESSKEYID', secretKey: 'YOUR-SECRETACCESSKEY' }) var outFile = fs.createWriteStream('your_localfile.zip'); var fileStat = Fs.stat(file, function(e, stat) { if (e) { return console.log(e) } s3Client.putObject('mybucket', 'hello/remote_file.zip', 'application/octet-stream', stat.size, fileStream, function(e) { return console.log(e) // should be null }) }) EOF 

putObject()在这里是一个完全托pipe的单个函数调用文件大小超过5MB,它自动内部多部分。 您也可以重新开始失败的上传,并通过validation以前上传的部分从停止的地方开始。

另外这个库也是同构的,也可以在浏览器中使用。

如果能够帮助任何能够成功从客户端stream向s3的人(无内存或磁盘存储):

https://gist.github.com/mattlockyer/532291b6194f6d9ca40cb82564db9d2a

服务器端点假定req是一个stream对象,我从客户端发送了一个File对象,现代浏览器可以将这个对象作为二进制数据发送,并在头文件中添加文件信息。

 const fileUploadStream = (req, res) => { //get "body" args from header const { id, fn } = JSON.parse(req.get('body')); const Key = id + '/' + fn; //upload to s3 folder "id" with filename === fn const params = { Key, Bucket: bucketName, //set somewhere Body: req, //req is a stream }; s3.upload(params, (err, data) => { if (err) { res.send('Error Uploading Data: ' + JSON.stringify(err) + '\n' + JSON.stringify(err.stack)); } else { res.send(Key); } }); }; 

是的,把文件信息放在标题中,但是如果你看一下这个要点,它比我用stream媒体库或者multer,busboy等等发现的任何东西都要干净得多。

+1为实用主义和感谢@SalehenRahman的帮助。