节点:如何使用管道并从多部分更改一个文件
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函数中,你的逻辑应该是这样的:
如果,在当前块中,你要修改的JSON开始
<SOME_DATA_BEFORE_JSON> <MY_JSON_START>
然后 this.push(SOME_DATA_BEFORE_JSON);
并将 MY_JSON_START
保存在本地变量中
当你的 JSON 还没有结束时,将块附加到你的本地 var
如果在当前块中,JSON结束:
<JSON_END> <SOME_DATA_AFTER_JSON>
然后将 JSON_END
添加到您的变量中,进行任何您想要的更改,
并推送更改:
this.push(local_var);
this.push(SOME_DATA_AFTER_JSON);
如果当前块没有你的JSON,只需推送块
this.push(chunk);
除此之外,您可能还想阅读 multipart format。
SOME_DATA_BEFORE_JSON
从上面将是:
--frontier
Content-Type: text/plain
<JSON_START>
除了Content-Type,还可能包含文件名、编码等。
需要记住的是,块可能会在任何地方结束(可能会在边界的中间结束)。
解析可能会变得非常棘手;我会搜索边界键(frontier),然后检查 JSON 是否在那之后开始。会有两种情况:
- 块:
<SOME_DATA> --frontier <FILE METADATA> <FILE_DATA>
- 区块 1:
<SOME_DATA> --fron
块 2:ier <FILE METADATA> <FILE_DATA>
希望对您有所帮助!
我有一个需要重定向请求的 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函数中,你的逻辑应该是这样的:
如果,在当前块中,你要修改的JSON开始
<SOME_DATA_BEFORE_JSON> <MY_JSON_START>
然后
this.push(SOME_DATA_BEFORE_JSON);
并将MY_JSON_START
保存在本地变量中当你的 JSON 还没有结束时,将块附加到你的本地 var
如果在当前块中,JSON结束:
<JSON_END> <SOME_DATA_AFTER_JSON>
然后将
JSON_END
添加到您的变量中,进行任何您想要的更改, 并推送更改:this.push(local_var);
this.push(SOME_DATA_AFTER_JSON);
如果当前块没有你的JSON,只需推送块
this.push(chunk);
除此之外,您可能还想阅读 multipart format。
SOME_DATA_BEFORE_JSON
从上面将是:
--frontier
Content-Type: text/plain
<JSON_START>
除了Content-Type,还可能包含文件名、编码等。 需要记住的是,块可能会在任何地方结束(可能会在边界的中间结束)。 解析可能会变得非常棘手;我会搜索边界键(frontier),然后检查 JSON 是否在那之后开始。会有两种情况:
- 块:
<SOME_DATA> --frontier <FILE METADATA> <FILE_DATA>
- 区块 1:
<SOME_DATA> --fron
块 2:ier <FILE METADATA> <FILE_DATA>
希望对您有所帮助!