如何禁用用于file upload的Express BodyParser(Node.js)

这似乎应该是一个相当简单的问题,但我很难找出如何处理它。

我使用Node.js + Express来构build一个Web应用程序,并且我发现在大多数情况下,expression公开的连接BodyParser是非常有用的。 不过,我希望能更细粒度地访问多部分表单数据POSTS,因为他们来了 – 我需要将inputstream传输到另一台服务器,并且希望避免首先下载整个文件。

因为我正在使用Express BodyParser,所有的file upload都会自动parsing,并在使用“request.files”之前上传并提供给我的任何函数。

有没有办法让我禁用BodyParser的多部分formdata职位,而不是禁用它的一切?

当你inputapp.use(express.bodyParser()) ,几乎每个请求都会经过bodyParser函数(执行哪一个函数将取决于Content-Type头)。

默认情况下,有3个头支持(AFAIR)。 你可以看到来源是肯定的。 您可以(重新)为Content-Type s定义处理程序,如下所示:

 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。

在Express 3中,事情已经发生了变化,所以我在工作项目中共享更新的代码( express.bodyParser() 之前应该是app.use ed):

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

还有一些关于原始问题的伪代码:

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

如果您需要使用express.bodyParser提供的function,但是您希望将其禁用为multipart / form-data,则技巧是不express.bodyParser directly使用express.bodyParser directlyexpress.bodyParser是一种方便的方法,它包含了另外三种方法: express.jsonexpress.urlencodedexpress.multipart

所以,而不是说

 app.use(express.bodyParser()) 

你只需要说

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

这为您提供了大部分数据的bodyparser的所有好处,同时允许您独立处理formdata上传。

编辑: jsonurlencoded现在不再与Express捆绑在一起。 它们是由单独的body-parser模块提供的,现在按如下方式使用它们:

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

如果对正文parsing的需求仅取决于路由本身,最简单的方法是仅将bodyParser用作路由中间件function,而不是仅在需要的路由上使用它,而不是在应用范围内使用它:

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

在Express 3中,您可以将parameter passing给bodyParser作为{defer: true} – 它将推迟多部分处理并将Formidable表单对象公开为req.form。 意思是你的代码可以是:

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

有关更详细的强大事件处理,请参阅https://github.com/felixge/node-formidable

我在3.1.1遇到过类似的问题,发现(不是很漂亮的IMO)解决scheme:

禁用multipart / form-data的bodyParser:

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

并parsing内容:

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

例如,我正在使用节点多方自定义代码应该看起来像这样:

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

抛出这是在app.configure之前

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