Express BodyParser uitschakelen voor bestandsuploads (Node.js)

Dit lijkt een vrij eenvoudige vraag te zijn, maar ik vind het heel moeilijk om erachter te komen hoe ik dit moet aanpakken.

Ik gebruik Node.js + Express om een ​​webtoepassing te bouwen, en ik vind de connect BodyParser die express blootstelt in de meeste gevallen erg handig. Ik zou echter graag meer gedetailleerde toegang hebben tot meerdelige formuliergegevens-POSTS zodra ze komen – ik moet de invoerstroom naar een andere server sturen en wil voorkomen dat ik eerst het hele bestand download.

Omdat ik de Express BodyParser gebruik, worden alle bestandsuploads echter automatisch geparseerd en geüpload en beschikbaar gemaakt met “request.files” voordat ze ooit bij een van mijn functies komen.

Is er een manier waarop ik de BodyParser kan uitschakelen voor meerdelige formdata-berichten zonder deze voor al het andere uit te schakelen?


Antwoord 1, autoriteit 100%

Als je de functionaliteit van express.bodyParserwilt gebruiken, maar deze wilt uitschakelen voor multipart/form-data, is de truc om express.bodyParser directly. express.bodyParseris een gemaksmethode die drie andere methoden omvat: express.json, express.urlencodeden express.multipart.

Dus in plaats van te zeggen

app.use(express.bodyParser())

je hoeft alleen maar te zeggen

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

Dit geeft u alle voordelen van de bodyparser voor de meeste gegevens, terwijl u de uploads van formuliergegevens onafhankelijk kunt afhandelen.

Bewerken:jsonen urlencodedworden nu niet meer gebundeld met Express. Ze worden geleverd door de afzonderlijke module body-parseren u gebruikt ze nu als volgt:

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

Antwoord 2, autoriteit 44%

Als de noodzaak voor body-parsing alleen afhangt van de route zelf, is het eenvoudigste om bodyParserte gebruiken als een route-middleware-functie op alleen de routes die het nodig hebben, in plaats van het app-breed te gebruiken:

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

Antwoord 3, autoriteit 29%

Als u app.use(express.bodyParser())typt, gaat bijna elk verzoek door de bodyParser-functies (welke wordt uitgevoerd, hangt af van content-typekop).

Standaard worden er 3 headers ondersteund (AFAIR). Voor de zekerheid zou je bronnen kunnen raadplegen. U kunt handlers voor content-type‘s (her)definiëren met zoiets als dit:

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.

Er zijn dingen veranderd in Express 3, dus ik deel bijgewerkte code van een werkend project (moet app.useed voorexpress.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);
  };
};

En wat pseudo-code, met betrekking tot de oorspronkelijke vraag:

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

Antwoord 4, autoriteit 24%

Binnen Express 3 kun je de parameter doorgeven aan de bodyParserals {defer: true}– wat in term de verwerking van meerdere delen uitstelt en het Formidable-formulierobject blootstelt als req. formulier. Dit betekent dat uw code kan zijn:

...
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){
    })
}

Voor meer gedetailleerde afhandeling van formidabele gebeurtenissen raadpleegt u https://github.com/felixge/node-formidable


Antwoord 5, autoriteit 6%

Ik heb soortgelijke problemen ondervonden in 3.1.1 en heb een (niet zo mooie IMO) oplossing gevonden:

om bodyParser voor multipart/form-data uit te schakelen:

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

en voor het ontleden van de inhoud:

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

Ik gebruik bijvoorbeeld node-multiparty waar de aangepaste code er als volgt uit zou moeten zien:

   var form = new multiparty.Form();
    form.on('file',function(name,file){
       //...per file event handling
    });     
    form.parse(req, function(err, fields, files) {
       //...next();
    });

Antwoord 6, autoriteit 5%

Met express v4 en body-parser v1.17 en hoger,
U kunt een functie doorgeven in het typevan bodyParser.json.
body-parser zal alleen die invoer ontleden waar deze functie een waarheidswaarde retourneert.

app.use(bodyParser.json({
    type: function(req) {
        return req.get('content-type').indexOf('multipart/form-data') !== 0;
    },
}));

In de bovenstaande code,
de functie retourneert een valse waarde als het content-typemultipart/form-datais.
Het analyseert de gegevens dus niet wanneer het content-typemultipart/form-datais.


Antwoord 7, autoriteit 2%

gooi dit voor app.configure

delete express.bodyParser.parse['multipart/form-data'];

Other episodes