2016-08-09 1 views
4

У меня есть служба http, которая должна перенаправить запрос, я не использую потоки, потому что я имею дело с большими файлами в multipart и переполняет RAM или диск (см. How do Node.js Streams work?)Узел: Как я могу использовать трубку и изменить один файл из multipart

Теперь я использую трубы, и она работает, код что-то в этом роде:

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

Единственным недостатком этого является то, что в этом цикле я RESEND в трубе содержит один файл в формате JSON, который требуется несколько полей для изменения.

Могу ли я использовать трубку и изменить один файл в многопоточном канале?

ответ

1

Вы можете сделать это, используя 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 не закончился, добавьте кусок к локальному вару

  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 format. SOME_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>

Надеется, что это помогает!