这是我自己的问题的答案。我希望它能帮助有同样问题的人。
首先:您无法在正常的应用程序代码(例如控制器,模型)中观察文件上传的进度事件。我尝试使用似乎有效的前置过滤器,直到我意识到它破坏了方法覆盖。这就是为什么我必须编写自己的非常简单的中间件,它只监听 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 (with 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);
});
};