2016-08-09 3 views
4

J'ai un service http qui doit rediriger une requête, je n'utilise pas de flux parce que je traite de gros fichiers en multipart et il submerge la RAM ou le disque (voir How do Node.js Streams work?)Noeud: Comment puis-je utiliser un tube et modifier un fichier d'un multipart

maintenant, je suis en utilisant des tuyaux et il fonctionne, le code est quelque chose de ce genre:

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

la seule lacune est que dans ce multipart je Renvoyez le tube contient un fichier JSON a besoin de quelques champs à changer. Puis-je continuer à utiliser un tube et modifier un fichier dans la multipartie canalisée?

Répondre

1

Vous pouvez le faire en utilisant un 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); 

Transformer le code Stream:

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

Dans la fonction _transform, votre logique devrait être quelque chose comme ceci:

  1. Si, dans le morceau en cours, le JSON vous voulez modifier commence

    <SOME_DATA_BEFORE_JSON> <MY_JSON_START>

    puis this.push(SOME_DATA_BEFORE_JSON); et garder MY_JSON_START dans une var locale

  2. Bien que votre JSON n'a pas terminé, ajoutez le morceau à votre var locale

  3. Si, dans le morceau en cours, la fin JSON:

    <JSON_END> <SOME_DATA_AFTER_JSON>

    puis ajoutez JSON_END à votre var, faites les changements que vous voulez, et pousser les changements: this.push(local_var); this.push(SOME_DATA_AFTER_JSON);

  4. Si morceau actuel n'a rien de votre JSON, il suffit de pousser le morceau

    this.push(chunk);

Autre que cela, vous pouvez lire le multipart format. SOME_DATA_BEFORE_JSON d'en haut sera:

--frontier 
Content-Type: text/plain 

<JSON_START> 

autre que le contenu-type, il peut contenir le nom, l'encodage, etc. Quelque chose à garder à l'esprit les morceaux peuvent mettre fin à chaque fois que (pourrait se terminer au milieu de la frontière). L'analyse syntaxique pourrait être assez compliquée. Je voudrais rechercher la clé de frontière (frontière), puis vérifier si le JSON commence après cela.Il y aurait deux cas:

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

Hope this helps!