2016-08-09 408 views
4

Ich habe einen http-Dienst, der eine Anfrage umleiten muss, ich verwende keine Streams, weil ich mit großen Dateien in multipart und es überfordert RAM oder Festplatte (siehe How do Node.js Streams work?)Knoten: Wie kann ich Pipe und ändern Sie eine Datei aus einem Multipart

Jetzt habe ich Rohre verwende und es funktioniert, ist der Code etwas dieser Art:

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

der einzige Nachteil ist, dass in diesem mehrteiliger ich in das Rohr erneut enthält eine JSON-Datei, muss ein paar Felder geändert werden.

Kann ich noch eine Pipe verwenden und eine Datei im Pipe-Multipart ändern?

Antwort

1

Sie können dies mit einem Transform Stream tun.

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); 

Stream-Code-Transformation:

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(); 
}; 

In der _transform Funktion sollten Sie Ihre Logik so etwas wie dieses:

  1. Wenn im aktuellen Brocken, die JSON Sie wollen Änderung beginnt

    <SOME_DATA_BEFORE_JSON> <MY_JSON_START>

    dann this.push(SOME_DATA_BEFORE_JSON); und halten MY_JSON_START in einem lokalen var

  2. Während Ihre JSON nicht beendet ist, fügen Sie den Brocken zu Ihrem lokalen var

  3. Wenn im aktuellen Brocken, die JSON endet:

    <JSON_END> <SOME_DATA_AFTER_JSON>

    dann JSON_END zu Ihrem var hinzuzufügen, zu tun, was Änderungen, die Sie wollen, und drücken Sie die Änderungen: this.push(local_var); this.push(SOME_DATA_AFTER_JSON);

  4. Wenn aktuelle Brocken nichts von Ihrer JSON hat, drücken Sie einfach die Brocken

    this.push(chunk);

Other than that, können Sie die multipart format lesen. SOME_DATA_BEFORE_JSON aus wird oben sein:

--frontier 
Content-Type: text/plain 

<JSON_START> 

Anders als Content-Type, die Dateinamen enthalten kann, Codierung usw. Etwas im Auge zu behalten, die Brocken enden können, wo (in der Mitte der Grenze enden könnte). Das Parsing könnte ziemlich schwierig werden; Ich würde nach dem Grenzschlüssel (Grenze) suchen und dann überprüfen, ob der JSON danach startet.Es gäbe zwei Fällen:

  1. Brocken: <SOME_DATA> --frontier <FILE METADATA> <FILE_DATA>
  2. chunk 1: <SOME_DATA> --fron Chunk 2: ier <FILE METADATA> <FILE_DATA>

hoffe, das hilft!