如何编写Node.js模块来处理传入的管道流

时间:2016-01-15 22:08:33

标签: javascript node.js stream

我试图编写一个接受传入管道二进制(或base-64编码)流的节点模块,但坦率地说,我甚至不知道从哪里开始。我无法在Node文档中看到有关处理传入流的任何示例;我只看到消费它们的例子?

比如说我希望能够做到这一点:

var asset = new ProjectAsset('myFile', __dirname + '/image.jpg')
var stream = fs.createReadStream(__dirname + '/image.jpg', { encoding: 'base64' }).pipe(asset)
stream.on('finish', function() {
    done()
})

我已经ProjectAsset看起来像这样,但我不知道下一步该去哪里:

'use strict'

var stream = require('stream'),
    util = require('util')

var ProjectAsset = function() {
    var self = this

    Object.defineProperty(self, 'binaryData', {
        configurable: true,
        writable: true
    })

    stream.Stream.call(self)

    self.on('pipe', function(src) {
        // does it happen here? how do I set self.binaryData?
    })

    return self
}

util.inherits(ProjectAsset, stream.Stream)

module.exports = ProjectAsset
module.exports.DEFAULT_FILE_NAME = 'file'

3 个答案:

答案 0 :(得分:4)

可以继承"Condition": {"StringLike": {"aws:Referer": [ ... ]}}并使其有效,但是根据我建议从documentation继承的stream.Writable中的可用内容。管道输入stream.Stream您需要定义_write(chunk, encoding, done)来处理管道。这是一个例子:

stream.Writable

项目资产

var asset = new ProjectAsset('myFile', __dirname + '/image.jpg')
var stream = fs.createReadStream(__dirname + '/image.jpg', { encoding: 'base64' }).pipe(asset)
stream.on('finish', function() {
    console.log(asset.binaryData);
})

如果您还希望阅读'use strict' var stream = require('stream'), util = require('util') var ProjectAsset = function() { var self = this self.data self.binaryData = []; stream.Writable.call(self) self._write = function(chunk, encoding, done) { // Can handle this data however you want self.binaryData.push(chunk.toString()) // Call after processing data done() } self.on('finish', function() { self.data = Buffer.concat(self.binaryData) }) return self } util.inherits(ProjectAsset, stream.Writable) module.exports = ProjectAsset module.exports.DEFAULT_FILE_NAME = 'file' ,请查看继承stream.Duplex并包含_read(size)方法。

如果您正在做更简单的事情,还有simplified constructors api

答案 1 :(得分:2)

由于您使用var asset = new ProjectAsset('myFile', __dirname + '/image.jpg')我认为您的ProjectAsset职责是采取一些输入流做一些转换并将其写入文件。您可以实现转换流,因为您从流中接收一些输入并生成一些可以保存到文件或其他写入流的输出。

您当然可以通过继承node.js Transform Stream来实现转换流,但继承非常麻烦,因此我的实现使用through2来实现转换流:

module.exports = through2(function (chunk, enc, callback) {
  // This function is called whenever a piece of data from the incoming stream is read
  // Transform the chunk or buffer the chunk in case you need more data to transform

  // Emit a data package to the next stream in the pipe or omit this call if you need more data from the input stream to be read
  this.push(chunk);

  // Signal through2 that you processed the incoming data package
  callback();
 }))

用法

var stream = fs.createReadStream(__dirname + '/image.jpg', { encoding: 'base64' })
               .pipe(projectAsset)
               .pipe(fs.createWriteStream(__dirname + '/image.jpg'));

正如您在本示例中所见,实现流管道可以完全解耦数据转换并保存数据。

工厂职能

如果您更喜欢在项目资产模块中使用类似构造函数的方法,因为您需要传递一些值或事物,您可以轻松导出构造函数,如下所示

var through2 = require('through2');

module.exports = function(someData) {

  // New stream is returned that can use someData argument for doing things
  return through2(function (chunk, enc, callback) {
    // This function is called whenever a piece of data from the incoming stream is read
    // Transform the chunk or buffer the chunk in case you need more data to transform

    // Emit a data package to the next stream in the pipe or omit this call if you need more data from the input stream to be read
    this.push(chunk);

    // Signal through2 that you processed the incoming data package
    callback();
  });
}

<强>用法

var stream = fs.createReadStream(__dirname + '/image.jpg', { encoding: 'base64' })
               .pipe(projectAsset({ foo: 'bar' }))
               .pipe(fs.createWriteStream(__dirname + '/image.jpg'));

答案 2 :(得分:2)

我不确定这是不是你要找的东西,但我认为你可以使用缓冲区api和Buffer.concat来处理它,缓冲数组可以在流上从chunk检索data听众

'use strict'

var stream = require('stream'),
    util = require('util');

var ProjectAsset = function() {
    var self = this

    Object.defineProperty(self, 'binaryData', {
        configurable: true,
        writable: true
    })

    stream.Stream.call(self)
    var data;
    var dataBuffer=[];
    self.on('data', function(chunk) {
        dataBuffer.push(chunk);
    }).on('end',function(){
        data=Buffer.concat(dataBuffer);
    });
    self.binaryData=data.toString('binary');
    return self
}

util.inherits(ProjectAsset, stream.Stream)

module.exports = ProjectAsset
module.exports.DEFAULT_FILE_NAME = 'file'