Как отключить Express BodyParser для загрузки файлов (Node.js)

Кажется, это должен быть довольно простой вопрос, но мне очень трудно понять, как к нему подойти.

Я использую Node.js + Express для создания веб-приложения, и я считаю, что Connect BodyParser, который предоставляет Express, очень полезен в большинстве случаев. Однако мне бы хотелось иметь более детальный доступ к многостраничным ПОСТ-данным формы по мере их поступления - мне нужно перенаправить входной поток на другой сервер, и сначала я хочу избежать загрузки всего файла.

Однако поскольку я использую Express BodyParser, все загружаемые файлы анализируются автоматически, загружаются и доступны с использованием & quot; request.files & quot; до того, как они дойдут до любой из моих функций.

Есть ли способ для меня отключить BodyParser для составных сообщений форм-данных, не отключая его для всего остального?

 meloncholy08 окт. 2012 г., 19:11
Aaaarg! Я только что потратил целый день, пытаясь понять, почему я не могу загрузить файлы, когда образец приложения (без Express, но также, очевидно, со многими другими отличиями) работал идеально. ОказываетсяbodyParser виновник Спасибо за вопрос.

Ответы на вопрос(7)


Вы можете передать функцию вtype bodyParser.json.
body-parser будет анализировать только те входные данные, где эта функция возвращает истинное значение.

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

В приведенном выше коде,
функция возвращает ложное значение, еслиcontent-type являетсяmultipart/form-data.
Таким образом, он не анализирует данные, когдаcontent-type являетсяmultipart/form-data.

проще всего воспользоваться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);
 12 сент. 2014 г., 20:58
Отличный ответ.

ое) решение:

отключить bodyParser для 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);
});

и для разбора содержимого:

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.bodyParser но вы хотите отключить его для multipart / form-data, хитрость в том, чтобы не использоватьexpress.bodyParser directly. express.bodyParser это удобный метод, который включает три других метода:express.json, express.urlencoded, а такжеexpress.multipart.

Так что вместо того, чтобы сказать

app.use(express.bodyParser())

тебе просто нужно сказать

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

Это дает вам все преимущества bodyparser для большинства данных, в то же время позволяя вам независимо обрабатывать загрузку форм-данных.

Edit: json а такжеurlencoded больше не связаны с Express. Они предоставляются отдельнымтело-анализатор модуль и теперь вы используете их следующим образом:

bodyParser = require("body-parser")
app.use(bodyParser.json())
   .use(bodyParser.urlencoded())
 02 июл. 2012 г., 18:18
Или вы можете определить свой собственныйbodyParser заmultipart/form-data Заголовок Content-Type:require('express').bodyParser.parse['multipart/form-data'] = function yourHandler(req, options, next)...
 11 дек. 2017 г., 13:40
Это должен быть принятый ответ! Чистый & amp; Чисто
 Myk03 июл. 2012 г., 19:09
Это даже лучше - если вы отправите это как ответ с коротким образцом кода, я сделаю его приемлемым ответом для потока. Замечательно, как трудно было найти эту простую информацию. Спасибо!
 14 февр. 2013 г., 23:05
Это очень удобно знать, особенно для уменьшения зависимости подключаемых приложений!
 26 февр. 2013 г., 22:22
@Myk Я отредактировал ответ для большей ясности; надеюсь, вы можете пометить его как принятый сейчас.
Решение Вопроса

app.use(express.bodyParser()), почти каждый запрос будет проходитьbodyParser функции (какая из них будет выполняться зависит отContent-Type заголовок).

По умолчанию поддерживается 3 заголовка (AFAIR). Вы могли видеть источники, чтобы быть уверенным. Вы можете (пере) определить обработчики дляContent-Typeс чем-то вроде этого:

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 все изменилось, поэтому я делюсь обновленным кодом из рабочего проекта (должно бытьapp.useиздание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);
  };
};

И некоторый псевдокод относительно оригинального вопроса:

function disableParserForContentType(req, res, next) {
  if (req.contentType in options.contentTypes) {
    req._body = true;
    next();
  }
}
 04 июл. 2012 г., 17:43
Или вы можетеdelete express.bodyParser.parse['multipart/form-data']; before app.use(express.bodyParser()) как предложил @jwerre.

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

 02 апр. 2014 г., 21:42
Кажется, что Formidable больше не входит в Express 4. См.github.com/felixge/node-formidable/issues/264
 09 апр. 2013 г., 03:44
Я не уверен, что не делаю ничего плохого, но слушатели событий не будут работать в моем случае. Я проверил исходный код multipart.js и вызовов промежуточного программного обеспечения после синтаксического анализа целых данных (и нет возможности вызвать их дважды), поэтому в вашем примере события генерируются перед назначением

delete express.bodyParser.parse['multipart/form-data'];
 06 февр. 2013 г., 03:57
у меня это тоже вылетает :(
 Myk05 июл. 2012 г., 17:10
Я пробовал это в разных частях моего кода, и это всегда приводило к немедленному падению приложения.
 05 июл. 2012 г., 18:10
Вы положили его до того, как создали экземпляр вашего bodyParser? Если нет, вы должны это сделать.

Ваш ответ на вопрос