如何禁用用于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 directly
。 express.bodyParser
是一种方便的方法,它包含了另外三种方法: express.json
, express.urlencoded
和express.multipart
。
所以,而不是说
app.use(express.bodyParser())
你只需要说
app.use(express.json()) .use(express.urlencoded())
这为您提供了大部分数据的bodyparser的所有好处,同时允许您独立处理formdata上传。
编辑: json
和urlencoded
现在不再与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'];