繁体   English   中英

如何禁用Express BodyParser进行文件上传(Node.js)

[英]How to disable Express BodyParser for file uploads (Node.js)

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

我正在使用Node.js + Express构建一个Web应用程序,我发现表达公开的连接BodyParser在大多数情况下非常有用。 但是,我希望对多部分表单数据POSTS进行更细粒度的访问 - 我需要将输入流传输到另一台服务器,并且希望避免首先下载整个文件。

但是,因为我正在使用Express BodyParser,所有文件上传都会自动解析并上传,并且在他们访问我的任何功能之前使用“request.files”可用。

有没有办法让我为多部分formdata帖子禁用BodyParser而不禁用其他所有内容?

如果你需要使用express.bodyParser提供的功能,但你想为multipart / form-data禁用它,那就是不要express.bodyParser directly使用express.bodyParser directly express.bodyParser是一个方便的方法,它包含三个其他方法: express.jsonexpress.urlencodedexpress.multipart

所以不要说

app.use(express.bodyParser())

你只需要说

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

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

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

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

如果身体解析的需要仅取决于路由本身,最简单的方法是仅在需要它的路由上使用bodyParser作为路由中间件函数,而不是在应用程序范围内使用它:

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

当您键入app.use(express.bodyParser()) ,几乎每个请求都将通过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 3中,您可以将参数传递给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)解决方案:

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

并解析内容:

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

例如,我正在使用node-multiparty,其中自定义代码应如下所示:

    var form = new multiparty.Form();

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

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

使用express v4和body-parser v1.17及更高版本,
您可以传递bodyParser.json type的函数。
body-parser将仅解析此函数返回truthy值的那些输入。

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

在上面的代码中,
如果content-typemultipart/form-data则该函数返回一个假值。
因此,当content-typemultipart/form-data时,它不会解析multipart/form-data

抛出这是在app.configure之前

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM