pipestream到s3.upload()

我目前正在使用名为s3-upload-stream的node.js插件将非常大的文件传输到Amazon S3。 它使用多部分API,大部分它工作得很好。

但是,这个模块正在显示其年龄,我已经不得不对其进行修改(作者也不赞同)。 今天我遇到了亚马逊的另一个问题,我真的想采取作者的build议,并开始使用官方aws-sdk来完成我的上传。

但。

官方的SDK似乎不支持pipe道到s3.upload() 。 s3.upload的本质是你必须将可读stream作为parameter passing给S3构造函数。

我有大约120多个用户代码模块进行各种文件处理,他们不知道他们输出的最终目的地。 引擎递给他们一个可移动的可写入输出stream,然后他们将其传送给它。 我不能给他们一个AWS.S3对象,并要求他们调用upload()而不向所有模块添加代码。 我使用s3-upload-stream的原因是因为它支持pipe道。

有没有办法使aws-sdk s3.upload()东西,我可以pipestream的?

使用node.js stream.PassThrough()stream包装S3 upload()函数。

这是一个例子:

 inputStream .pipe(uploadFromStream(s3)); function uploadFromStream(s3) { var pass = new stream.PassThrough(); var params = {Bucket: BUCKET, Key: KEY, Body: pass}; s3.upload(params, function(err, data) { console.log(err, data); }); return pass; } 

在接受的答案中,function在上传完成之前结束,因此是不正确的。 下面的代码从可读stream正确地pipe道。

上传参考

 async function uploadReadableStream(stream) { return new Promise((resolve, reject) => { const params = {Bucket: bucket, Key: key, Body: stream}; s3.upload(params, function(err, data) { console.log(err, data); if (err) { reject(err); return; } resolve(data); }); } async function upload() { const readable = getSomeReadableStream(); const results = await uploadReadableStream(readable); console.log('upload complete', results); } 

您还可以进一步使用ManagedUpload来输出进度信息,例如:

 const manager = s3.upload(params, function(err, data) { console.log(err, data); if (err) { reject(err); return; } resolve(data); }); manager.on('httpUploadProgress', (progress) => { console.log('progress', progress) // { loaded: 4915, total: 192915, part: 1, key: 'foo.jpg' } }); 

ManagedUpload参考

如果能够帮助任何人成功地从客户端stream向s3,

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

服务器端代码假定req是一个stream对象,在我的情况下,它是从客户端发送的,并在头文件中设置文件信息。

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

是的,它打破了惯例,但如果你看看的要点是比我发现使用Muller,公务员等…更清洁。

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

如果你知道stream的大小,你可以使用minio-js来上传stream:

  s3Client.putObject('my-bucketname', 'my-objectname.ogg', stream, size, 'audio/ogg', function(e) { if (e) { return console.log(e) } console.log("Successfully uploaded the stream") })