何时在node.js上传脚本中检查文件大小/ mimetype?

我使用express / formidable在node.js中创build了一个上传脚本。 它基本上工作,但我想知道在什么时候检查上传的文件,例如最大的文件大小,或者如果该文件的mimetype实际上是允许的。

我的程序看起来像这样:

app.post('/', function(req, res, next) { req.form.on('progress', function(bytesReceived, bytesExpected) { // ... do stuff }); req.form.complete(function(err, fields, files) { console.log('\nuploaded %s to %s', files.image.filename, files.image.path); // ... do stuff }); }); 

在我看来,检查mimetype /文件大小的唯一可行的地方是complete事件,我可以可靠地使用文件系统函数来获取上传文件的大小/tmp/ – 但是这似乎不是一个好主意因为:

  • 可能恶意/太大的文件已经上传到我的服务器上
  • 用户体验很差 – 您只能看到上传过程后才告知它没有工作

实施这个最好的做法是什么? 我在node.js中发现了很多file upload的例子,但似乎没有做我需要的安全检查。

在节点IRC和节点邮件列表中的一些人的帮助下,我做了以下工作:

我正在使用强大的处理file upload。 使用progress事件,我可以像这样检查最大文件大小:

 form.on('progress', function(bytesReceived, bytesExpected) { if (bytesReceived > MAX_UPLOAD_SIZE) { console.log('### ERROR: FILE TOO LARGE'); } }); 

可靠地检查mimetype要困难得多。 基本的想法是使用progress事件,然后如果足够的file upload使用file --mime-type调用,并检查该外部命令的输出。 简化它看起来像这样:

 // contains the path of the uploaded file, // is grabbed in the fileBegin event below var tmpPath; form.on('progress', function validateMimetype(bytesReceived, bytesExpected) { var percent = (bytesReceived / bytesExpected * 100) | 0; // pretty basic check if enough bytes of the file are written to disk, // might be too naive if the file is small! if (tmpPath && percent > 25) { var child = exec('file --mime-type ' + tmpPath, function (err, stdout, stderr) { var mimetype = stdout.substring(stdout.lastIndexOf(':') + 2, stdout.lastIndexOf('\n')); console.log('### file CALL OUTPUT', err, stdout, stderr); if (err || stderr) { console.log('### ERROR: MIMETYPE COULD NOT BE DETECTED'); } else if (!ALLOWED_MIME_TYPES[mimetype]) { console.log('### ERROR: INVALID MIMETYPE', mimetype); } else { console.log('### MIMETYPE VALIDATION COMPLETE'); } }); form.removeListener('progress', validateMimetype); } }); form.on('fileBegin', function grabTmpPath(_, fileInfo) { if (fileInfo.path) { tmpPath = fileInfo.path; form.removeListener('fileBegin', grabTmpPath); } }); 

Connect(2.x.)的新版本已经使用限制中间件将其插入到bodyParser : https : //github.com/senchalabs/connect/blob/master/lib/middleware/multipart.js#L44-61

我认为这种方式好多了,因为当超过最大限制的时候就终止请求,而不是停止强大的parsing器(并让请求“继续”)。

有关限制中间件的更多信息: http : //www.senchalabs.org/connect/limit.html