Как отключить Express BodyParser для загрузки файлов (узел.Яш)
кажется, это должен быть довольно простой вопрос, но мне очень трудно понять, как к нему подойти.
Я использую Node.JS + Express для создания веб-приложения, и я считаю, что connect BodyParser, который express предоставляет, очень полезен в большинстве случаев. Тем не менее, я хотел бы иметь более детальный доступ к составным формам-сообщениям данных по мере их поступления - мне нужно передать входной поток на другой сервер и избежать загрузки всего файла первый.
поскольку я использую Экспресс-BodyParser, однако, все загрузки файлов анализируются автоматически и загружаются и доступны с помощью " запроса.файлы", прежде чем они доберутся до любой из моих функций.
есть ли способ отключить BodyParser для сообщений multipart formdata, не отключая его для всего остального?
7 ответов
при вводе app.use(express.bodyParser())
, почти каждый запрос будет проходить через bodyParser
функции (которые будут выполняться в зависимости от Content-Type
заголовок).
по умолчанию поддерживаются 3 заголовка (AFAIR). Вы могли бы увидеть источники, чтобы быть уверенным. Вы можете (re)определить обработчики для 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 Все изменилось, поэтому я делюсь обновленным кодом из рабочего проекта (должно быть app.use
Эд до 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();
}
}
Если вам нужно использовать функциональность, предоставляемую 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 для большинства данных, позволяя обрабатывать загрузки formdata независимо.
Edit: json
и urlencoded
теперь больше не в комплекте с 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);
в пределах Express 3 Вы можете передать параметр в bodyParser
as {defer: true}
- который в термине откладывает многопартийную обработку и предоставляет грозный объект формы как req.форма. Значение вашего кода может быть:
...
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) решение:
чтобы отключить 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 v4 и body-parser v1.17 и выше,
Вы можете передать функцию в 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
.