Come disabilitare Express BodyParser per i caricamenti di file (Node.js)

Sembra che dovrebbe essere una domanda abbastanza semplice, ma sto attraversando un periodo difficile per capire come affrontarlo.

Sto usando Node.js + Express per creare un’applicazione web e trovo che la connessione BodyParser che esprime espone sia molto utile nella maggior parte dei casi. Tuttavia, mi piacerebbe avere un accesso più granulare a POSP form di dati multipart come sono – ho bisogno di redirect il stream di input a un altro server, e voglio evitare di scaricare l’intero file prima.

Poiché sto utilizzando Express BodyParser, tuttavia, tutti i caricamenti dei file vengono analizzati automaticamente e caricati e disponibili utilizzando “request.files” prima che possano accedere a una delle mie funzioni.

C’è un modo per me per disabilitare il BodyParser per i messaggi di formdata multipart senza distriggersrlo per tutto il resto?

Quando si digita app.use(express.bodyParser()) , quasi ogni richiesta passerà attraverso bodyParser funzioni bodyParser (che verrà eseguita a seconda dell’intestazione Content-Type ).

Di default, ci sono 3 intestazioni supportate (AFAIR). Potresti vedere le fonti per essere sicuro. È ansible (ri) definire i gestori per Content-Type s con qualcosa di simile a questo:

 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.

Le cose sono cambiate in Express 3, quindi sto condividendo il codice aggiornato dal progetto di lavoro (dovrebbe essere app.use ed before 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); }; }; 

E qualche pseudo-codice, riguardo alla domanda originale:

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

Se è necessario utilizzare la funzionalità fornita da express.bodyParser ma si desidera disabilitarlo per multipart / form-data, il trucco è di non utilizzare express.bodyParser directly . express.bodyParser è un metodo di convenienza che include tre altri metodi: express.json , express.urlencoded ed express.multipart .

Quindi, invece di dire

 app.use(express.bodyParser()) 

hai solo bisogno di dire

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

Questo ti offre tutti i vantaggi del bodyparser per la maggior parte dei dati e ti consente di gestire i caricamenti dei moduli in modo indipendente.

Modifica: json e urlencoded ora non sono più in bundle con Express. Vengono forniti dal modulo body parser separato e ora li usi come segue:

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

Se la necessità di parsing del corpo dipende solo dalla rotta stessa, la cosa più semplice è usare bodyParser come funzione middleware di rotta solo sui percorsi che ne hanno bisogno piuttosto che utilizzarla per tutta l’app:

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

All’interno di Express 3, è ansible passare il parametro a bodyParser come {defer: true} bodyParser {defer: true} – che in termine rimuove l’elaborazione multipart e espone l’object Form Formidable come req.form. Il tuo codice può significare:

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

Per una gestione degli eventi formidabile più dettagliata, consultare https://github.com/felixge/node-formidable

Ho affrontato problemi simili in 3.1.1 e trovato (non così bella IMO) soluzione:

disabilitare bodyParser per 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); }); 

e per analizzare il contenuto:

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

per esempio sto usando node-multiparty dove il codice personalizzato dovrebbe apparire così:

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

buttare questo è prima di app.configure

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

Con express v4 e body-parser v1.17 e successivi,
È ansible passare una funzione nel type di bodyParser.json.
body-parser analizzerà solo quegli input in cui questa funzione restituisce un valore di verità.

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

Nel codice sopra,
la funzione restituisce un valore falsy se il content-type è multipart/form-data .
Quindi, non analizza i dati quando il content-type è multipart/form-data .