使用节点js的S3文件上传流

时间:2014-02-09 10:00:41

标签: node.js file-upload amazon-s3

我正在尝试使用带有要求的节点js服务器在亚马逊S3上找到流文件的解决方案:

  • 不要将临时文件存储在服务器或内存中。但最多限制不完整文件,缓冲可用于上传。
  • 对上传文件大小没有限制。
  • 在完成文件上传之前不要冻结服务器,因为如果文件上传量很大,其他请求的等待时间会出乎意料 增加。

我不想使用浏览器直接上传文件,因为在这种情况下需要共享S3凭据。从节点js服务器上传文件的另一个原因是在上传文件之前可能还需要应用某些身份验证。

我尝试使用node-multiparty来实现这一点。但它并没有像预期的那样发挥作用。您可以在https://github.com/andrewrk/node-multiparty/issues/49查看我的解决方案和问题。它适用于小文件,但对于大小为15MB的文件失败。

任何解决方案或替代方案?

6 个答案:

答案 0 :(得分:26)

您现在可以使用official Amazon SDK for nodejs进行流媒体播放,甚至更精彩,您最终可以在不知道文件大小的情况下 。只需将流传递为Body

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

供您参考,v3 SDK 发布时带有一个专用模块来处理该用例:https://www.npmjs.com/package/@aws-sdk/lib-storage

我花了一段时间才找到它。

答案 3 :(得分:0)

我在工作项目s3-upload-stream中使用here模块。

@raynos在他的http-framework存储库中也有一些很好的例子。

答案 4 :(得分:0)

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

以下是流式上传的示例。

$ 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()这里是一个完全托管的单函数调用,文件大小超过5MB,它会在内部自动执行多部分。您也可以恢复失败的上传,它将通过验证以前上传的部分从其停止的位置开始。

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

答案 5 :(得分:0)

如果它可以帮助我能够成功地从客户端流式传输到s3(没有内存或磁盘存储):

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

服务器端点假设req是一个流对象,我从客户端发送了一个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);
    }
  });
};

是的,将文件信息放在标题符号约定中,但是如果你看一下要点,它比我使用流式库或multer,busboy等发现的任何其他信息要清晰得多......

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