Потоковая загрузка файлов на s3 через экспресс-сервер - PullRequest
0 голосов
/ 04 марта 2019

У меня есть экспресс-точка, где я сейчас занимаюсь загрузкой файлов.Большие файлы занимают много памяти, поскольку b / ci использовал bodyParser, который буферизирует весь файл в памяти перед вызовом моей функции обработчика.

Я удалил промежуточное ПО bodyParser из этой конечной точки, и я стараюсь правильно использовать потоки дляв основном потоковая передача файла -> экспресс -> s3.

Это документы по методу s3, и он принимает буфер или поток.

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

route

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 голосов
/ 04 марта 2019

Оказывается, ответ на самом деле очень прост.Все, что мне нужно было сделать, это передать объект 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

Затем я посмотрел документы Node и увидел, что http.IncomingMessage реализует интерфейс Readable Stream

Он реализует ReadableИнтерфейс потока, а также следующие дополнительные события, методы и свойства.

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

...