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

时间:2011-06-12 12:56:46

标签: file-upload node.js

我使用express / formidable在node.js中创建了一个上传脚本。它基本上有效,但我想知道在何时何地检查上传的文件e。 G。最大文件大小或实际允许文件的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中找到了很多文件上传的例子,但似乎没有人进行我需要的安全检查。

2 个答案:

答案 0 :(得分:3)

在节点IRC和节点邮件列表的一些人的帮助下,我就是这样做的:

我正在使用强力来处理文件上传。使用progress事件,我可以像这样检查最大文件大小:

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

可靠地检查mimetype要困难得多。基本的想法是使用progress事件,然后如果上传了足够的文件,则使用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);
    }
});

答案 1 :(得分:0)

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

我认为这样做要好得多,因为你只是在超过最大限制时终止请求,而不是仅停止强大的解析器(并让请求“继续”)。

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