I'm getting the "POST" value from browser to nodejs and express.
I post the file to nodejs.
Below is the code.
var express = require('express')
, routes = require('./routes')
, http = require('http');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
//app.use(express.bodyParser());
app.use(express.bodyParser({
uploadDir: __dirname + '/upload',
keepExtensions: true,
limit: '50mb'
}));
app.use(express.limit('35mb'));
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.post('/', function(request, response){
console.log(request.body.upfile);
console.log(request.files);
var ret = {a:'a',b:'b'};
response.writeHead(200, { 'Content-Type': 'application/json'});
response.write(JSON.stringify(ret));
response.end();
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
It can receive the post file.
But I have set the file size limit to 50mb.
When I'm post the file size larger than 50mb.
The browser will continue to upload the file until finish.
What I need is when size larger than 50mb. It response 413(request entity too large, that is what express error print out) http code to browser that stop it uploading.
I've investigate the express source code.
It use connect that locate in
node_modules/express/node_modules/connect/lib/middleware/limit.js of line 45.
That it log the 413 and the call stack to stdio.
I think I can do the trick here to response to browser with 413 http code.
But when I test it. The browser print reset.
Below is the modify code.
module.exports = function limit(bytes){
if ('string' == typeof bytes) bytes = utils.parseBytes(bytes);
if ('number' != typeof bytes) throw new Error('limit() bytes required');
return function limit(req, res, next){
var received = 0
, len = req.headers['content-length']
? parseInt(req.headers['content-length'], 10)
: null;
// self-awareness
if (req._limit) return next();
req._limit = true;
// limit by content-length
if (len && len > bytes) {
var ret = {a:'bbbbb',b:'b'};
res.writeHead(413);
res.write(JSON.stringify(ret));
res.end();
return next(utils.error(413));
}
// limit
req.on('data', function(chunk){
received += chunk.length;
if (received > bytes) req.destroy();
});
next();
};
};
What happens here is that the first "if":
// limit by content-length
if (len && len > bytes) {
var ret = {a:'bbbbb',b:'b'};
res.writeHead(413);
res.write(JSON.stringify(ret));
res.end();
return next(utils.error(413));
}
is executed only if the browser sent the 'content-length' header, which is not always the case. Most of the time it will fallback to counting the bytes on-the-fly here:
// limit
req.on('data', function(chunk){
received += chunk.length;
if (received > bytes) req.destroy();
});
But as you can see, when it goes past the allowed limit it simply destroys the request, which results in a reset message from the browser. You could change it to be like this:
// limit
req.on('data', function(chunk){
received += chunk.length;
if (received > bytes) {
var ret = {a:'bbbbb',b:'b'};
res.writeHead(413);
res.write(JSON.stringify(ret));
res.end();
}
});
It seems to work, but I'm not sure if this is the right way to do it.