Преобразовать поток в буфер?

Как преобразовать поток в буфер в nodejs? Вот мой код для анализа файла в почтовом запросе в экспресс.

app.post('/upload', express.multipart({
defer: true
}), function(req, res) {
req.form.on('part', function(part) {

//Here I want to convert the streaming part into a buffer.
//do something buffer-specific task

  var out = fs.createWriteStream('image/' + part.filename);
  part.pipe(out);
});

req.form.on('close', function() {
    res.send('uploaded!');
  });
});

Ответы

Ответ 1

Вы можете использовать модуль stream-to, который может преобразовывать читаемые данные потока в массив или буфер:

var streamTo = require('stream-to');
req.form.on('part', function (part) {
  streamTo.buffer(part, function (err, buffer) {
    // Insert your business logic here
  });
});

Если вы хотите лучше понять, что происходит за кулисами, вы можете реализовать логику самостоятельно, используя поток Writable. Как разработчик потока для записи, вам нужно определить только одну функцию: метод _write, который будет вызываться каждый раз, когда некоторые данные записываются в поток. Когда поток ввода завершит передачу данных, будет отправлено событие end: затем мы создадим буфер, используя метод Buffer.concat.

var stream = require('stream');
var converter = new stream.Writable();
converter.data = []; // We'll store all the data inside this array
converter._write = function (chunk) {
  this.data.push(chunk);
};
converter.on('end', function() { // Will be emitted when the input stream has ended, ie. no more data will be provided
  var b = Buffer.concat(this.data); // Create a buffer from all the received chunks
  // Insert your business logic here
});

Ответ 2

Вместо того, чтобы конвейер, вы можете присоединить data и end обработчики событий к потоку part для его чтения:

var buffers = [];
part.on('data', function(buffer) {
  buffers.push(buffer);
});
part.on('end', function() {
  var buffer = Buffer.concat(buffers);
  ...do your stuff...

  // write to file:
  fs.writeFile('image/' + part.filename, buffer, function(err) {
    // handle error, return response, etc...
  });
});

Однако это будет читать всю загрузку в память. Если это проблема, возможно, вам стоит подумать о создании настраиваемого потока для преобразования входящих данных, но это может быть не тривиально.