节点:如何使用管道并从多部分更改一个文件

Node: How can I use pipe and change one file from a multipart

我有一个需要重定向请求的 http 服务,我没有使用流,因为我处理多部分的大文件并且它会占用 RAM 或磁盘(参见

现在我正在使用管道并且它可以工作,代码是这样的:

var Req = getReq(response);
request.pipe(Req);

唯一的缺点是,在我重新发送的这个多部分中,管道包含一个 JSON 需要更改几个字段的文件。

我还能使用管道并更改管道多部分中的一个文件吗?

您可以使用 Transform Stream 来完成此操作。

var Req = getReq(response);
var transformStream = new TransformStream();

// the boundary key for the multipart is in the headers['content-type']
// if this isn't set, the multipart request would be invalid
Req.headers['content-type'] = request.headers['content-type'];

// pipe from request to our transform stream, and then to Req
// it will pipe chunks, so it won't use too much RAM
// however, you will have to keep the JSON you want to modify in memory
request.pipe(transformStream).pipe(Req);

转换流代码:

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

var TransformStream = function() {
  Transform.call(this, {objectMode: true});
};
util.inherits(TransformStream, Transform);

TransformStream.prototype._transform = function(chunk, encoding, callback) {

// here should be the "modify" logic;

// this will push all chunks as they come, leaving the multipart unchanged
// there's no limitation on what you can push
// you can push nothing, or you can push an entire file
  this.push(chunk);
  callback();
};

TransformStream.prototype._flush = function (callback) {
    // you can push in _flush
    // this.push( SOMETHING );      
    callback();
};

在_transform函数中,你的逻辑应该是这样的:

  1. 如果,在当前块中,你要修改的JSON开始

    <SOME_DATA_BEFORE_JSON> <MY_JSON_START>

    然后 this.push(SOME_DATA_BEFORE_JSON); 并将 MY_JSON_START 保存在本地变量中

  2. 当你的 JSON 还没有结束时,将块附加到你的本地 var

  3. 如果在当前块中,JSON结束:

    <JSON_END> <SOME_DATA_AFTER_JSON>

    然后将 JSON_END 添加到您的变量中,进行任何您想要的更改, 并推送更改: this.push(local_var); this.push(SOME_DATA_AFTER_JSON);

  4. 如果当前块没有你的JSON,只需推送块

    this.push(chunk);

除此之外,您可能还想阅读 multipart formatSOME_DATA_BEFORE_JSON 从上面将是:

--frontier
Content-Type: text/plain

<JSON_START>

除了Content-Type,还可能包含文件名、编码等。 需要记住的是,块可能会在任何地方结束(可能会在边界的中间结束)。 解析可能会变得非常棘手;我会搜索边界键(frontier),然后检查 JSON 是否在那之后开始。会有两种情况:

  1. 块:<SOME_DATA> --frontier <FILE METADATA> <FILE_DATA>
  2. 区块 1:<SOME_DATA> --fron 块 2:ier <FILE METADATA> <FILE_DATA>

希望对您有所帮助!