Javascript 如何为文件上传禁用 Express BodyParser (Node.js)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11295554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:21:14  来源:igfitidea点击:

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

javascriptnode.jsfile-uploadexpressconnect

提问by Myk

This seems like it should be a fairly simple question, but I'm having a really hard time figuring out how to approach it.

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

I'm using Node.js + Express to build a web application, and I find the connect BodyParser that express exposes to be very useful in most cases. However, I would like to have more granular access to multipart form-data POSTS as they come - I need to pipe the input stream to another server, and want to avoid downloading the whole file first.

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

Because I'm using the Express BodyParser, however, all file uploads are parsed automatically and uploaded and available using "request.files" before they ever get to any of my functions.

但是,因为我使用的是 Express BodyParser,所以所有文件上传都会在它们到达我的任何函数之前自动解析并使用“request.files”上传和可用。

Is there a way for me to disable the BodyParser for multipart formdata posts without disabling it for everything else?

有没有办法让我禁用多部分表单数据帖子的 BodyParser 而不禁用其他所有内容?

采纳答案by Aleksei Zabrodskii

When you type app.use(express.bodyParser()), almost each request will go through bodyParserfunctions (which one will be executed depends on Content-Typeheader).

当您键入 时app.use(express.bodyParser()),几乎每个请求都会通过bodyParser函数(执行哪个取决于Content-Type标头)。

By default, there are 3 headers supported (AFAIR). You could see sources to be sure. You can (re)define handlers for Content-Types with something like this:

默认情况下,支持 3 个标头 (AFAIR)。你可以看到消息来源。您可以(重新)定义Content-Types 的处理程序,如下所示:

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.更新。

Things have changed in Express 3, so I'm sharing updated code from working project (should be app.useed beforeexpress.bodyParser()):

Express 3 中的事情发生了变化,所以我正在共享来自工作项目的更新代码(应该在app.useed之前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);
  };
};

And some pseudo-code, regarding original question:

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

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

回答by Myk

If you need to use the functionality provided by express.bodyParserbut you want to disable it for multipart/form-data, the trick is to not use express.bodyParser directly. express.bodyParseris a convenience method that wraps three other methods: express.json, express.urlencoded, and express.multipart.

如果您需要express.bodyParser使用express.bodyParser directly. express.bodyParser是一个封装其它三种方法一个方便的方法:express.jsonexpress.urlencoded,和express.multipart

So instead of saying

所以与其说

app.use(express.bodyParser())

you just need to say

你只需要说

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

This gives you all the benefits of the bodyparser for most data while allowing you to handle formdata uploads independently.

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

Edit:jsonand urlencodedare now no longer bundled with Express. They are provided by the separate body-parsermodule and you now use them as follows:

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

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

回答by ebohlman

If the need for body parsing depends only on the route itself, the simplest thing is to use bodyParseras a route middleware function on only the routes that need it rather than using it app-wide:

如果正文解析的需要仅取决于路由本身,最简单的方法是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);

回答by alekperos

Within Express 3, you can pass parameter to the bodyParseras {defer: true}- which in term defers multipart processing and exposes the Formidable form object as req.form. Meaning your code can be:

在 Express 3 中,您可以将参数传递给bodyParseras {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){


    })
}

For more detailed formidable event handling refer to https://github.com/felixge/node-formidable

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

回答by JakubKnejzlik

I've faced similar problems in 3.1.1 and found (not so pretty IMO) solution:

我在 3.1.1 中遇到了类似的问题,并找到了(IMO 不太漂亮)解决方案:

to disable bodyParser for multipart/form-data:

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

and for parsing the content:

并解析内容:

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

for example I'm using node-multiparty where the custom code should look like this:

例如,我正在使用节点多方,其中自定义代码应如下所示:

    var form = new multiparty.Form();

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

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

回答by itch96

With express v4, and body-parser v1.17 and above,
You can pass a function in the typeof bodyParser.json.
body-parser will parse only those inputs where this function returns a truthy value.

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

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

In the above code,
the function returns a falsy value if the content-typeis multipart/form-data.
So, it does not parse the data when the content-typeis multipart/form-data.

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

回答by jwerre

throw this is before app.configure

抛出这是在 app.configure 之前

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