【问题标题】:Upload-Progress in compoundjs/express with bodyParser({defer:true}) fails使用bodyParser({defer:true})的compoundjs / express中的上传进度失败
【发布时间】:2013-05-07 08:23:29
【问题描述】:

我试图弄清楚如何正确使用 express(和compoundjs)中使用的 bodyParser 的延迟属性。 目标是访问 event-property,这应该可以通过将 defer-property 传递给 bodyParser。

发生的情况是,bodyParser 对enctype=multipart/form-data 根本不起作用。 在我看来,bodyParser 仍然应该解析请求并将所有相关数据放在 body-Object 中。但是对于我使用带有 enctype=multipart/form-data 的表单的每个请求,body-Object 都是空的。这会导致几个错误,例如 authetification failureforgery-Check

那么 - 这里发生了什么?我是不是理解错了什么? bodyParser 应该完成它的工作,我想访问进度事件。

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

};

【问题讨论】:

    标签: upload express progress compoundjs


    【解决方案1】:

    这是我自己问题的答案。我希望它能帮助有同样问题的人。

    首先:您无法在正常的应用程序代码(例如控制器、模型)中观察文件上传的进度事件。 我尝试使用似乎有效的前过滤器,直到我意识到它破坏了方法覆盖。 这就是为什么我必须编写自己的非常简单的中间件,它只监听 req.form 的进度和结束事件,记录进度并在结束事件发生时调用 next()。

    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" 的形式委托给您。然后你的中间件可以观察上传。 之后 Session 和 Cookies 被加载。我试图在我的中间件之前加载会话和 cookie,以了解当前正在上传的用户是否有权这样做,但这会导致非常有线的行为。我可以阅读会话,一切看起来都很好,但我在表单对象中的所有数据都翻了一番。 {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);
        });
    
    };
    

    【讨论】:

      猜你喜欢
      • 2020-01-30
      • 2012-10-23
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2013-03-28
      • 2014-08-11
      相关资源
      最近更新 更多