【问题标题】:when to check for file size/mimetype in node.js upload script?何时检查 node.js 上传脚本中的文件大小/mimetype?
【发布时间】:2011-06-12 12:56:46
【问题描述】:

我使用 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 中找到了很多文件上传示例,但似乎没有一个进行我需要的安全检查。

【问题讨论】:

    标签: file-upload node.js


    【解决方案1】:

    在节点 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);
        }
    });
    

    【讨论】:

    • @CIRK 它的工作,但是我只是在一些宠物项目中使用它,而不是在生产中。该请求稍后在控制器中关闭(我使用 express.js 作为框架)。如果您有兴趣,请随时在 github 上查看该项目的完整源代码:github.com/maxbeutel/nodejs.fileupload - 虽然我从未完全完成它,但它是 node.js 中的一次有趣的冒险;)
    【解决方案2】:

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

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

    更多关于限制中间件:http://www.senchalabs.org/connect/limit.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多