Как отключить Экспресс BodyParser для загрузки файлов (узел.js)
похоже, что это должен быть довольно простой вопрос, но мне очень трудно понять, как к нему подойти.
Я использую узел.js + Express для создания веб-приложения, и я считаю, что connect BodyParser, который предоставляет express, очень полезен в большинстве случаев. Тем не менее, я хотел бы иметь более детальный доступ к составным формам-сообщениям данных по мере их поступления - мне нужно передать входной поток на другой сервер и избежать загрузки всего файла первый.
поскольку я использую Экспресс-BodyParser, однако, все загрузки файлов анализируются автоматически и загружаются и доступны с помощью " запроса.файлы" прежде чем они попадают в мои функции.
есть ли способ отключить BodyParser для сообщений multipart formdata, не отключая его для всего остального?
7 ответов:
при вводе
app.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, поэтому я делюсь обновленным кодом из рабочего проекта (должно быть
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
как{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 и нашел (не так красиво ИМО) решение:
чтобы отключить 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
.