Скачать файл с s3 без записи его в файловую систему в nodejs - PullRequest
0 голосов
/ 17 октября 2018

У меня сервер Nodejs, работающий с Hapi.

одна из задач сервера - отправлять файлы в API обслуживающего устройства (API принимает потоки только при отправке буфера, он возвращает ошибку) пользователюask

Все файлы хранятся в s3.Когда я загружаю их, если использую обещание (), я попадаю в буфер тела.И я могу получить проход, если я использую createReadStream ().

Моя проблема заключается в том, когда я пытаюсь преобразовать буфер в поток и отправить его, API отклоняет его, и то же самое, когда я использую createReadStream ()результат, но когда я использую FS для сохранения файла, а затем FS для чтения API, принимаю поток и его работу.

, поэтому мне нужна помощь, как создать тот же результат без сохранения и чтения файла.

edit: вот мой код, я знаю, что это неправильный путь, но он работает, мне нужен лучший способ, который будет работать

static async downloadFile(Bucket, Key) {
    const result = await s3Client
      .getObject({
        Bucket,
        Key
      })
      .promise();
    fs.writeFileSync(`${Path.basename(Key)}`,result.Body);

    const file = await fs.createReadStream(`${Path.basename(Key)}`);
    return file;
  }

1 Ответ

0 голосов
/ 17 октября 2018

Если я правильно понимаю, вы хотите получить объект из корзины s3 и передать его в свой HTTP-ответ в виде потока.

Вместо того, чтобы получать данные в буферах, а потом искать способпреобразование его в поток может быть сложным и имеет свои ограничения: если вы действительно хотите использовать мощь потоков, не пытайтесь преобразовать его в буфер и загрузить весь объект в память, вы можете создать запрос, который передает возвращаемый потокданные напрямую в объект потока Node.js путем вызова метода createReadStream по запросу.

Вызов createReadStream возвращает необработанный поток HTTP, управляемый запросом.Затем поток необработанных данных может быть передан в любой объект потока Node.js.

Этот метод полезен для вызовов служб, которые возвращают необработанные данные в своей полезной нагрузке, таких как вызов getObject объекта службы Amazon S3 для потоковой передачи данных.непосредственно в файл, как показано в этом примере.

//I Imagine you have something similar.
server.get ('/image', (req, res) => {
    let s3 = new AWS.S3({apiVersion: '2006-03-01'});
    let params = {Bucket: 'myBucket', Key: 'myImageFile.jpg'};
    let readStream= s3.getObject(params).createReadStream();
    // When the stream is done being read, end the response
    readStream.on('close', () => {
        res.end()
    })

    readStream.pipe(res);
});

При потоковой передаче данных из запроса с использованием createReadStream возвращаются только необработанные данные HTTP.SDK не выполняет постобработку данных, эти необработанные HTTP-данные могут быть возвращены напрямую.

Примечание: Поскольку Node.js не может перемотать большинство потоков, если запрос первоначально выполняется успешно,тогда логика повтора отключена для остальной части ответа.В случае сбоя сокета во время потоковой передачи SDK не будет пытаться повторить попытку или отправить дополнительные данные в поток.Логика вашего приложения должна выявлять такие потоковые сбои и обрабатывать их.

Правки: После правок исходного вопроса я вижу, что s3 отправляет объект потока PassThrough, который отличается отFileStream в Nodejs.Поэтому, чтобы обойти проблему, используйте память (если ваши файлы не очень большие и у вас достаточно памяти).

Используйте пакет memfs, он заменит собственный fs в вашем приложении https://www.npmjs.com/package/memfs

Установите пакет по npm install memfs и потребуйте следующее:

    const {fs} = require('memfs');

и ваш код будет выглядеть как

 static async downloadFile(Bucket, Key) {
        const result = await s3
        .getObject({
          Bucket,
          Key
        })
        .promise();
      fs.writeFileSync(`/${Key}`,result.Body);

      const file = await fs.createReadStream(`/${Key}`);
      return file;
    }

Обратите внимание, что единственное изменение, которое яЯ сделал в ваших функциях то, что я изменил путь ${Path.basename(Key)} на /${Key}, потому что теперь вам не нужно знать путь к вашей исходной файловой системе, мы храним файлы в памяти.Я проверил, и это решение работает

...