Busboy Сохранить Steam для использования позже - PullRequest
0 голосов
/ 19 января 2019

Я пытаюсь использовать busboy , чтобы разрешить клиентам загружать файлы на мой веб-сервер Express.

У меня есть следующая промежуточная функция, которую я использую для Express.

module.exports = (req, res, next) => {
    req.files = {};

    let busboy;
    try {
        busboy = new Busboy({
            headers: req.headers
        });
    } catch (e) {
        return next();
    }

    busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
        req.files[fieldname] = {
            file,
            filename,
            encoding,
            mimetype
        };

        // Need to call `file.resume` to consume the stream somehow (https://stackoverflow.com/a/24588458/894067)
        file.resume();
    });
    busboy.on("finish", next);

    req.pipe(busboy);
};

Как видите, мне пришлось добавить file.resume();, чтобы было вызвано событие "финиша", и вызвать функцию next для промежуточного программного обеспечения (https://stackoverflow.com/a/24588458/894067).

.проблема, позже, когда я хочу использовать поток, он говорит readable: false. Поэтому я предполагаю, что file.resume(); отбрасывает поток и не позволяет использовать его в будущем.

Я в основном хочу получить все загруженные файлы и информацию, связанную с этими файлами, сохранить их в объекте req.files, затем использовать потоки позже или не использовать их, если я не хочу их использовать. Таким образом, они остаютсяпотоков и не занимают много памяти, пока я не буду готов использовать поток и фактически что-то с ним делать (или выбрать для его удаления).

Что я могу использовать вместо file.resume(); дляубедитесь, что событие «финиш» получает триггеры, апобудить меня использовать поток позже в жизненном цикле запроса (фактические маршруты app.post вместо промежуточного программного обеспечения)?

Клиент также может загружать несколько файлов.Поэтому мне нужно любое решение для обработки нескольких файлов.

1 Ответ

0 голосов
/ 29 января 2019

Если вы хотите обработать несколько файлов в одном запросе, процедура немного сложная.

Busboy проходит через один поток и генерирует события всякий раз, когда файлы поступают (последовательно).Вы не можете получить отдельные потоки для всех файлов одновременно с Busboy.Это не ограничение библиотеки, вот как работает HTTP.

Лучшим вариантом будет хранить все файлы во временном хранилище и хранить информацию для следующих промежуточных программ с помощью res.locals:

const Busboy = require('busboy');
const path = require('path');
const fs = require('fs');

module.exports = (req, res, next) => {
  res.locals.files = {};
  // You need to ensure the directory exists
  res.locals.someTemporaryDirectory = '/some/temp/dir/with/randomString/in/it';

  let busboy;
  try {
    busboy = new Busboy({
      headers: req.headers
    });
  } catch (e) {
    return next(e);
  }

  busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
    res.locals.files[fieldname + '_' + filename] = {
      filename,
      encoding,
      mimetype
    };
    // I skipped error handling for the sake of simplicity. Cleanup phase will be required as well 
    const tempFilePath = path.join(res.locals.someTemporaryDirectory, fieldname + '_' + filename);
    file.pipe(fs.createWriteStream(tempFilePath));
  });

  busboy.on("finish", next);

  req.pipe(busboy);
};

Следующее промежуточное программное обеспечение должно использовать res.locals.someTemporaryDirectory и res.locals.files для ведения бизнеса (для этого потребуется этап очистки).

Это решение может показаться неоптимальным, но HTTPкак есть.Возможно, вы захотите выдать отдельный HTTP-запрос для каждого файла, но я бы не рекомендовал его, поскольку вы столкнетесь с кучей других проблем (таких как синхронизация всех запросов + управление памятью).

Независимо от решенияэто требует, чтобы ваши руки пачкались.

...