когда проверить размер файла / mimetype в скрипте загрузки node.js? - PullRequest
5 голосов
/ 12 июня 2011

Я создал скрипт загрузки в node.js, используя express / formidable.Это в основном работает, но мне интересно, где и когда проверить загруженный файл, например, на предмет максимального размера файла или действительно ли допустим 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 / file - это событие complete, где я могу надежно использовать файловую систему.функции для получения размера загруженного файла в /tmp/ - но это кажется не очень хорошей идеей, потому что:

  • возможно вредоносный / слишком большой файл уже загружен на мой сервер
  • пользовательский опыт плохой - вы наблюдаете за процессом загрузки, просто чтобы узнать, что он впоследствии не работал

Каков наилучший метод для реализации этого?Я нашел немало примеров для загрузки файлов в node.js, но ни один из них, похоже, не делал проверки безопасности, которые мне понадобятся.

Ответы [ 2 ]

3 голосов
/ 15 июня 2011

С помощью некоторых ребят из 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);
    }
});
0 голосов
/ 20 июня 2012

Новая версия Connect (2.x.) уже запекла в bodyParser с использованием промежуточного программного обеспечения лимита: https://github.com/senchalabs/connect/blob/master/lib/middleware/multipart.js#L44-61

Я думаю, что это намного лучше, так как вы просто убиваете запрос, когда он превышает максимальный предел, вместо того, чтобы просто остановить грозный парсер (и позволить запросу "продолжаться").

Подробнее о предельном промежуточном программном обеспечении: http://www.senchalabs.org/connect/limit.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...