2012-07-02 12 views
57

これはかなり簡単な質問であるようですが、私はそれに近づける方法を考え出すのに本当に苦労しています。ファイルアップロード(Node.js)のためにExpress BodyParserを無効にする方法

私はNode.js + Expressを使ってWebアプリケーションを構築していますが、ほとんどの場合、エクスプレッションを非常に便利に表現するconnect BodyParserが見つかりました。しかし、マルチパートフォームデータPOSTSへのより詳細なアクセスを望みます。入力ストリームを別のサーバーにパイプする必要があり、最初にファイル全体をダウンロードしないようにします。

私はExpress BodyParserを使用しているため、すべてのファイルアップロードは自動的に解析され、アップロードされ、「request.files」を使用して利用可能になります。

マルチパートフォームデータポストのBodyParserを他のすべてのものに対して無効にしないで無効にする方法はありますか?

+1

Aaaargを!私は一日以上、なぜサンプル・アプリケーション(Expressなしで、明らかに他の多くの違いもあります)が完璧に動作したときに、ファイルをアップロードできなかった理由を理解しようとしました。 'bodyParser'が原因であることが判明しました。これを聞いてくれてありがとう。 – meloncholy

答えて

16

WHEですあなたがapp.use(express.bodyParser())と入力した場合、ほとんどの場合、それぞれの要求はbodyParser機能を経由します(どちらが実行されるかは、Content-Typeヘッダーによって異なります)。

デフォルトでは、3つのヘッダーがサポートされています(AFAIR)。あなたは確かな情報源を見ることができます。

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:あなたは(再)このようなものでContent-Typeのためのハンドラを定義することができます。

物事はエクスプレス3に変更されているので、私は働いプロジェクト(express.bodyParser()app.useする必要があります)から更新されたコードを共有しています:元の質問については、

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

そして、いくつかの擬似コード:用語のどのマルチ延期 - エクスプレス3以内

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

または、あなたは '@ ** ** app.use(express.bodyParser())'の前にexpress.bodyParser.parse ['multipart/form-data']; – elmigranto

61

express.bodyParserで提供されている機能を使用する必要があるが、マルチパート/フォームデータで無効にしたい場合は、express.bodyParser directlyを使用しないでください。 express.bodyParserは、express.json,express.urlencoded、およびexpress.multipartの3つのメソッドをラップする便利なメソッドです。

ので、代わりの

app.use(express.bodyParser()) 

を言って、あなたはちょうどあなたが独立してFORMDATAアップロードを処理できるようにしながら

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

これは、あなたが最もデータのためのbodyparserのすべての利点を与える言う必要があります。

編集:jsonおよびurlencodedは、Expressにバンドルされなくなりました。これらは別々のbody-parserモジュールで提供し、次のように、あなたは今、それらを使用しています

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

また、 'multipart/form-data'のContent-Typeヘッダに独自の' bodyParser'を定義することもできます:bodyParser.parse ['multipart/form-data'] = function yourHandler(req、options 、next)... ' – elmigranto

+0

これはさらに優れています。短いコードサンプルを使って答えを提出すれば、そのスレッドに対して受け入れられる回答にします。そのシンプルな情報がどれほど見つけにくいかがはっきりと分かります。ありがとう! – Myk

+0

これは、特にマウントされたアプリケーションの依存関係を間引くために、本当に便利です! – wprl

27

体の解析の必要性が唯一のルート自体に依存している場合、最も簡単なものだけでルートミドルウェア機能としてbodyParser使用することですそれを使用するのではなく、それを必要とするルートは、APP-ワイド:

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

優秀な回答。 – antonio081014

1

スローこれは前app.configure

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

私はコード内のさまざまな部分でそれを試みましたが、いつもすぐにアプリをクラッシュさせました。 – Myk

+0

bodyParserをインスタンス化する前に入れましたか?もしそうでなければ、それを行うべきです。 – jwerre

+0

それは私のためにもクラッシュします:( – nick

15

、あなたは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){ 


    }) 
} 

私は解決策(ではないので、かなりIMO)3.1.1で同様の問題に直面して見つけたhttps://github.com/felixge/node-formidable

+0

私は間違ったことはしていないのかどうか分かりませんが、イベントリスナーは私の場合は動かないでしょう。 2回呼び出す可能性があるので)、あなたの割り当て前にイベントが送出されます。 – JakubKnejzlik

+2

FormidableはExpress 4に含まれていないようです。https://github.com/felixge/node-formidable/issues/264を参照してください。 –

4

を参照してください取り扱うより詳細な恐るべき出来事について:

マルチパート/フォームデータの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 
}); 

例えば私は、カスタムコードは次のようになります。ノードのマルチパーティを使用しています:

var form = new multiparty.Form(); 

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

    form.parse(req, function(err, fields, files) { 
     //...next(); 
    }); 
関連する問題