通过Express服务器将文件流传输到s3

时间:2019-03-04 03:06:30

标签: javascript node.js express amazon-s3

我有一个明确的端点,目前我负责处理文件上传。大文件占用大量内存b / c我正在使用bodyParser,该函数在调用处理程序函数之前将整个文件缓冲在内存中。

我从该端点上删除了bodyParser中间件,并且我在努力使用流从根本上流化文件上传-> express-> s3。

这是s3方法的文档,它接受缓冲区或流。

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property

路线

router.put('/files/:filename', putHandler({ s3Client: s3Client }))

我尝试过将文件流式传输到我的处理程序方法,但似乎并没有将其流式传输到s3.upload方法(真的不足为奇)

function put ({ s3Client }) {
  return (req, res) => {
        ...
        let whenFileUploaded = new Promise((resolve, reject) => {
          // const { Readable } = require('stream')
          // const inStream = new Readable({
            // read() {}
          // })

          let data = ''
          req.on('data', function (chunk) {
            req.log.debug('in chunk')
            data += chunk
            // inStream.push(chunk)
          })
          req.on('end', function () {
            req.log.debug('in end')
          })

          s3Client.upload(
            {
              Key: filepath,
              Body: data,
              SSECustomerAlgorithm: 'AES256',
              SSECustomerKey: sseKey.id.split('-').join('')
            },
            {
              partSize: 16 * 1024 * 1024, // 16mb
              queuSize: 1
            },
            (err, data) => err ? reject(err) : resolve(data)
          )
        })

我的猜测是,我需要创建一个流并将req.on('data...管道到我的流中,然后设置Body: inStream,您可以看到我尝试使用已注释掉的内容,但这似乎并没有要么工作。

帮助?

1 个答案:

答案 0 :(得分:0)

结果答案实际上很简单。我要做的就是传递req对象。

function put ({ s3Client }) {
  return (req, res) => {
        ...
        let whenFileUploaded = new Promise((resolve, reject) => {
          s3Client.upload(
            {
              Key: filepath,
              Body: req, // <-- NOTE THIS LINE
              SSECustomerAlgorithm: 'AES256',
              SSECustomerKey: sseKey.id.split('-').join('')
            },
            {
              partSize: 16 * 1024 * 1024, // 16mb
              queuSize: 1
            },
            (err, data) => err ? reject(err) : resolve(data)
          )
        })

我发现这种情况的方式是b / c,我查看了req对象是什么的快速源代码,并且看到它是http.IncomingMessage对象-https://github.com/expressjs/express/blob/master/lib/request.js#L31 < / p>

然后我查看了Node文档,发现http.IncomingMessage实现了Readable Stream接口

  

它实现了Readable Stream接口,以及以下内容   其他事件,方法和属性。

https://nodejs.org/docs/latest-v9.x/api/http.html#http_class_http_incomingmessage