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

时间:2016-08-09 15:32:27

标签: node.js http stream pipe multipart

我有一个需要重定向请求的http服务,我没有使用流,因为我处理multipart中的大文件并且它压倒了RAM或磁盘(参见How do Node.js Streams work?

现在我正在使用管道并且它有效,代码就是这样的:

options="$PATH./bin/QuickAccessBarServlet/getContactBarLabels.json"

@SlingServlet(
        extensions = { "json" },
        metatype=true,
        methods = { "GET" }, 
        paths={"/bin/QuickAccessBarServlet"}, 
        selectors = QuickAccessBarServlet.SELECTOR_GET_CONTACT_BAR_LABELS)

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

我仍然可以使用管道并更改管道多部分中的一个文件吗?

1 个答案:

答案 0 :(得分:2)

您可以使用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保留在本地var

  2. 虽然你的JSON还没有结束,但是将这个块附加到你当地的var

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

    <JSON_END> <SOME_DATA_AFTER_JSON>

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

  4. 如果当前的块没有任何JSON,只需按下块

    即可

    this.push(chunk);

  5. 除此之外,您可能需要阅读multipart format。 上面的SOME_DATA_BEFORE_JSON将是:

    --frontier
    Content-Type: text/plain
    
    <JSON_START>
    

    除了Content-Type,它可能包含文件名,编码等。 有些事情要记住,块可能会在任何地方结束(可能在边界中间结束)。 解析可能会非常棘手;我会搜索边界键(边界),然后检查JSON是否在此之后启动。会有两种情况:

    1. chunk:<SOME_DATA> --frontier <FILE METADATA> <FILE_DATA>
    2. chunk 1:<SOME_DATA> --fron 块2:ier <FILE METADATA> <FILE_DATA>
    3. 希望这有帮助!