63 votes

Comment faire pour désactiver Express BodyParser pour l'upload de fichiers (Node.js)

Cela semble comme il devrait être assez simple question, mais je vais avoir bien du mal à trouver comment l'aborder.

Je suis à l'aide d'Node.js + Express pour créer une application web, et je trouve le connecter BodyParser qui expriment expose à être très utile dans la plupart des cas. Cependant, je voudrais avoir plus d'accès granulaire aux multipart de données de formulaire POSTES qu'ils viennent - j'ai besoin de canaliser le flux d'entrée vers un autre serveur, et que vous voulez éviter de télécharger le fichier entier premier.

Parce que je suis à l'aide de l'Express BodyParser, cependant, tous les téléchargements de fichiers sont automatiquement analysé et téléchargées et disponibles à l'aide de "demande.les fichiers avant qu'ils ne jamais arriver à l'un de mes fonctions.

Est-il un moyen pour moi de désactiver le BodyParser pour multipart formdata postes sans le désactiver pour tout le reste?

64voto

Myk Points 4083

Si vous avez besoin d'utiliser la fonctionnalité fournie par express.bodyParser mais que vous souhaitez la désactiver pour multipart/form-data, l'astuce est de ne pas utiliser express.bodyParser directly. express.bodyParser est une méthode pratique qui enveloppe les trois autres méthodes: express.json, express.urlencoded, et express.multipart.

Donc au lieu de dire

app.use(express.bodyParser())

vous avez juste besoin de le dire

app.use(express.json())
   .use(express.urlencoded())

Cela vous donne tous les avantages de la bodyparser pour la plupart des données tout en vous permettant de gérer formdata télécharge de manière indépendante.

Edit: json et urlencoded sont maintenant n'est plus livré avec Express. Ils sont fournis par l'séparé de corps-analyseur module et vous maintenant de les utiliser comme suit:

bodyParser = require("body-parser")
app.use(bodyParser.json())
   .use(bodyParser.urlencoded())

27voto

ebohlman Points 6938

Si la nécessité d'un organe de l'analyse dépend uniquement de la route elle-même, la chose la plus simple est d'utiliser bodyParser comme une voie middleware fonction uniquement sur les routes qui en ont besoin plutôt que de l'utiliser app-large:

var express=require('express');
var app=express.createServer();
app.post('/body', express.bodyParser(), function(req, res) {
    res.send(typeof(req.body), {'Content-Type': 'text/plain'});
});
app.post('/nobody', function(req, res) {
    res.send(typeof(req.body), {'Content-Type': 'text/plain'});
});
app.listen(2484);

18voto

elmigranto Points 830

Lorsque vous tapez app.use(express.bodyParser()), presque chaque demande de passer par bodyParser fonctions (dont l'un sera exécutée dépend Content-Type - tête).

Par défaut, il y a 3 têtes de prise en charge (AFAIR). Vous pourriez voir les sources pour être sûr. Vous pouvez (re)définir des gestionnaires d' Content-Types avec quelque chose comme ceci:

var express = require('express');
var bodyParser = express.bodyParser;

// redefine handler for Content-Type: multipart/form-data
bodyParser.parse('multipart/form-data') = function(req, options, next) {
  // parse request body your way; example of such action:
  // https://github.com/senchalabs/connect/blob/master/lib/middleware/multipart.js

  // for your needs it will probably be this:
  next();
}


upd.

Les choses ont changé dans l'Express 3, donc je suis le partage de mise à jour du code de travail du projet (qui devrait être app.useed avant d' express.bodyParser()):

var connectUtils = require('express/node_modules/connect/lib/utils');

/**
 * Parses body and puts it to `request.rawBody`.
 * @param  {Array|String} contentTypes Value(s) of Content-Type header for which
                                       parser will be applied.
 * @return {Function}                  Express Middleware
 */
module.exports = function(contentTypes) {
  contentTypes = Array.isArray(contentTypes) ? contentTypes
                                             : [contentTypes];
  return function (req, res, next) {
    if (req._body)
      return next();

    req.body = req.body || {};

    if (!connectUtils.hasBody(req))
      return next();

    if (-1 === contentTypes.indexOf(req.header('content-type')))
      return next();

    req.setEncoding('utf8');  // Reconsider this line!
    req._body   = true;       // Mark as parsed for other body parsers.
    req.rawBody = '';

    req.on('data', function (chunk) {
      req.rawBody += chunk;
    });

    req.on('end', next);
  };
};

Et certains pseudo-code, concernant la question d'origine:

function disableParserForContentType(req, res, next) {
  if (req.contentType in options.contentTypes) {
    req._body = true;
    next();
  }
}

15voto

alexi Points 446

Dans l'Express 3, vous pouvez passer des paramètres à l' bodyParser comme {defer: true} - ce qui, en terme diffère en plusieurs parties de traitement et expose l'excellente forme de l'objet req.forme. Ce qui signifie que votre code peut être:

...
app.use(express.bodyParser({defer: true}));

...
// your upload handling request 
app.post('/upload', function(req, res)) {
    var incomingForm = req.form  // it is Formidable form object

    incomingForm.on('error', function(err){

          console.log(error);  //handle the error

    })

    incomingForm.on('fileBegin', function(name, file){

         // do your things here when upload starts
    })


    incomingForm.on('end', function(){

         // do stuff after file upload
    });

    // Main entry for parsing the files
    // needed to start Formidables activity
    incomingForm.parse(req, function(err, fields, files){


    })
}

Pour de plus amples formidable de gestion des événements, reportez-vous à https://github.com/felixge/node-formidable

5voto

GrizzlyNetch Points 1314

J'ai été confronté à des problèmes similaires en 3.1.1 et trouvé (pas assez OMI) solution:

pour désactiver bodyParser pour multipart/form-data:

var bodyParser = express.bodyParser();
app.use(function(req,res,next){
    if(req.get('content-type').indexOf('multipart/form-data') === 0)return next();
    bodyParser(req,res,next);
});

et de l'analyse du contenu:

app.all('/:token?/:collection',function(req,res,next){
    if(req.get('content-type').indexOf('multipart/form-data') !== 0)return next();
    if(req.method != 'POST' && req.method != 'PUT')return next();
    //...use your custom code here
});

par exemple, je suis l'aide d'un noeud-multipartite où la coutume code devrait ressembler à ceci:

    var form = new multiparty.Form();

    form.on('file',function(name,file){
       //...per file event handling
    });     

    form.parse(req, function(err, fields, files) {
       //...next();
    });

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X