1

Express(and)で使われているbodyParsercompoundjsのdefer-propertyの正しい使い方を考えてみました。目標は、defer-property を bodyParser に渡すデュオが可能なはずの event-property へのアクセスを取得することです。

何が起こるかというと、 bodyParser が に対してまったく機能しないということですenctype=multipart/form-data。私の意見では、bodyParser は引き続きリクエストを解析し、すべての関連データを body-Object に配置する必要があります。しかし、ボディオブジェクトは、enctype=multipart/form-data のフォームを使用するリクエストごとに空です。authetification failureやのようないくつかのエラーが発生しforgery-Checkます。

それで - ここで何が起こっているのですか?私は何か間違ったことを理解しましたか?bodyParser はその仕事をするだけで、progress-event にアクセスしたいと思っています。

PS: bodyParser、sessionParser などを使用する順序によって発生するエラーについて読みました。したがって、ここに私の構成(compoundjs)があります:

module.exports = function (compound) {

var express = require('express');
var app = compound.app;

app.configure(function(){
    app.use(compound.assetsCompiler.init());
    app.use(express.static(app.root + '/public', { maxAge: 86400000 }));
    app.set('jsDirectory', '/javascripts/');
    app.set('cssDirectory', '/stylesheets/');
    app.set('cssEngine', 'less');
    app.set('view engine', 'ejs');
    // make sure you run `npm install browserify uglify-js`
    // app.enable('clientside');
    app.use(express.methodOverride());
    app.use(express.cookieParser('secret'));
    app.use(express.session({secret: 'secret'}));
    app.use(express.bodyParser({
            //keepExtensions: true,
            limit: 10000000, // 10M limit
            defer: true
    }));
    app.use(app.router);
});

};
4

1 に答える 1

1

これが私自身の質問に対する答えです。同じ問題を抱えている人に役立つことを願っています。

まず第一に、通常のアプリ コード (コントローラ、モデルなど) では、ファイル アップロードの進捗イベントを観察できません。メソッドのオーバーライドを破壊することに気付くまで、動作しているように見えた before-filter を使用しようとしました。そのため、進行状況をログに記録し、終了イベントが発生したときに next() を呼び出す req.form の進行状況と終了イベントをリッスンするだけの、独自の非常に単純なミドルウェアを作成する必要がありました。

module.exports = function (compound) {

    var express = require('express');
    var app = compound.app;

    app.configure(function(){
        app.use(compound.assetsCompiler.init());
        app.use(express.static(app.root + '/public', { maxAge: 86400000 }));
        app.set('jsDirectory', '/javascripts/');
        app.set('cssDirectory', '/stylesheets/');
        app.set('cssEngine', 'less');
        app.set('view engine', 'ejs');

        app.use(express.bodyParser({
                //keepExtensions: true,
                limit: 10000000, // 10M limit
                defer: true
        }));

        // Thats the middleware
        app.use(function(req, res, next){
            // Only use it if form isnt parsed yet through bodyParser
            if(!req.form){next();return;}

            req.form.on('progress', function(bytesReceived, bytesExpected) {
                console.log('progress: '+Math.round(bytesReceived/bytesExpected*100)+'%');

            req.form.on('end',function(){
                console.log('fileupload finished');
                next();
            });
        });

        app.use(express.cookieParser('secret'));
        app.use(express.session({secret: 'secret'}));
        app.use(express.methodOverride());
        app.use(app.router);
    });

};

ミドルウェア呼び出しの順序は非常に重要です。最初に bodyParser を呼び出す必要があります ( を使用defer:true)。これが完了すると、パーサーはすべての受信リクエストを解析し、フォームのみを委任enctype="multipart/form-data"できます。その後、ミドルウェアはアップロードを監視できます。その後、セッションと Cookie が読み込まれます。現在アップロードしているユーザーがそうする権利を持っているかどうかを知るために、ミドルウェアの前にセッションと Cookie をロードしようとしましたが、非常に有線の動作が発生しました。私はセッションを読むことができ、すべてが素晴らしいように見えますが、フォーム オブジェクトのすべてのデータが 2 倍になりました。{name:'dude'}メソッドオーバーライド{name:{0:'dude',1:'dude'}}も破壊するようになりました。この注文は、私が知っている唯一の作業中の注文です。

二重化されたデータに関する前述の問題の解決策がある場合は、どんな助けもいただければ幸いです:)

//編集: 上記の問題の解決策を見つけました。Probem は - もちろんいつものように - ミドルウェアの順序でした。ここでも、アップロードの進行状況とセッションによる認証で機能する「最終的な」コードは次のとおりです。

module.exports = 関数 (複合) {

    var express = require('express');
    var app = compound.app;

    app.configure(function(){
        app.use(compound.assetsCompiler.init());
        app.use(express.static(app.root + '/public', { maxAge: 86400000 }));
        app.set('jsDirectory', '/javascripts/');
        app.set('cssDirectory', '/stylesheets/');
        app.set('cssEngine', 'less');
        app.set('view engine', 'ejs');
        // make sure you run `npm install browserify uglify-js`
        // app.enable('clientside');

        // At the very first load Cookie and Session
        app.use(express.cookieParser('secret'));
        app.use(express.session({secret: 'secret'}));

        // Load the bodyParer then with defer:true
        app.use(express.bodyParser({
                //keepExtensions: true,
                limit: 10000000, // 10M limit
                defer: true
        }));

        // Now comes the own middleware with access to the session _and_ the progress
        app.use(function(req, res, next){

            console.log('searching for files to upload...');
            if(!req.form || req.form.type != 'multipart'){next();return;}

            console.log('check if user is autheticated...');
            if(!req.session.userId)
            {
                console.log('user is not authenticated. Throwing Error to prevent further upload!');
                try { throw new Error("Stopping file upload..."); } 
                catch (e) { res.end(e.toString()); }
                next();return;
            }

            console.log('file found - attaching events...');
            req.form.on('progress', function(bytesReceived, bytesExpected) {
                console.log('progress: '+Math.round(bytesReceived/bytesExpected*100)+'%');
            });

            req.form.on('end',function(){
                console.log('fileupload finished');
                next();
            });
        });

        app.use(express.methodOverride());
        app.use(app.router);
    });

};
于 2013-05-07T20:12:15.907 に答える