Назад | Перейти на главную страницу

Запретить загрузку больших файлов с помощью nginx

Я обслуживаю свой сайт, используя Nginx в качестве веб-сервера. Я предлагаю своим пользователям возможность загрузки (им разрешено отправлять изображения размером до 5 МБ), поэтому у меня есть директива: client_max_body_size 5M; в моей конфигурации сервера. Я заметил, что если я попытаюсь загрузить какой-либо файл, веб-сервер не предотвратит загрузку файлов большего размера. В качестве примера предположим, что я пытаюсь загрузить действительно большое видео (фильм) размером 700 МБ. Сервер не отклоняет загрузку мгновенно, но буферизует все данные (это занимает так много времени и замедляет работу сервера), и только в конце загрузки он возвращает 413 Request entity too large ошибка.

Итак, вопрос: есть ли способ правильно настроить Nginx для блокировки загрузки больших файлов, когда передаваемые данные начинают преодолевать мои client_max_body_size предел?

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

Редактировать:

Я использую php и Symfony2 как бэкэнд ...

Изменить (снова):

Вот что написано в моем error.log:

2013/01/28 11:14:11 [error] 11328#0: *37 client intended to send too large body: 725207449 bytes, client: 33.33.33.1, server: www.local.example.com, request: "POST /app_dev.php/api/image/add/byuploader HTTP/1.1", host: "local.example.com", referrer: "http://local.example.com/app_dev.php/"`

Странно то, что я слежу за своим nginx error.log с участием tail -f error.log и сообщение появляется сразу после начала загрузки (до ее завершения). Итак, nginx выполняет своего рода превентивную проверку, но не останавливает / не блокирует запрос на загрузку ...

Я также попытался проверить, получает ли php контроль над загрузкой, выполнив echo 'something'; die(); на странице, которая обрабатывает загрузку, но ничего не распечатала и не остановила запрос загрузки. Так что это должен быть nginx или некоторые внутренние компоненты php, которые заставят всю загрузку продолжаться, пока она не будет полностью передана ...

другое редактирование: вот вид моего top (мониторинг nginx и php), когда идет загрузка большого файла (nginx перегружается):

изменить: вот моя конфигурация nginx

server {
    listen   80;
    server_name www.local.example.com local.example.com;
    access_log /vagrant/logs/example.com/access.log;
    error_log /vagrant/logs/example.com/error.log;
    root   /vagrant/example.com/web;
    index app.php;
    client_max_body_size 6M;

    location /phpmyadmin {
        root /usr/share;
        index index.php;
        location ~* \.php {
            fastcgi_intercept_errors on;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            include fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            fastcgi_param  HTTPS              off;
        }
    }

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /app.php/$1 last;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ ^/(app|app_dev)\.php(/|$) {
        fastcgi_intercept_errors on;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  HTTPS              off;
    }
}

Полезная информация здесь: https://stackoverflow.com/questions/4947107/nginx-upload-client-max-body-size-issue

Цитирую часть самого интересного ответа (для моего случая):

Большинство клиентов не читают ответы, пока не будет отправлено все тело запроса. Поскольку nginx закрывает соединение, клиент отправляет данные в закрытый сокет, вызывая TCP RST.

Если это так, то это проблема только браузера, которая не повлияет (не перегрузит) мой веб-сервер. Кажется, он жалуется на мою проверку памяти, которая показала, что и nginx, и php-fastcgi не были действительно перегружены при загрузке большого (700 МБ) файла.

Я мог бы решить проблему браузера несколькими способами, например:

  • добавить <input type="hidden" name="MAX_FILE_SIZE" value="5242880" /> в моей форме
  • использовать настраиваемую страницу ошибки 413 nginx

Что вы используете php или rails или что-то в этом роде? потому что вы должны проверить размер перед загрузкой.
устанавливать post_max_size и upload_max_filesize к соответствующему значению в файл: php.ini

изменить: попробуйте написать что-то подобное в свою загрузку

$element = new Zend_Form_Element_File('foo');
$element->setLabel('Upload a file:')
        ->setDestination('/var/www/upload');
// make sure its only 1 file
$element->addValidator('Count', false, 1);
// Maximal 100k
$element->addValidator('Size', false, 102400);
// only JPEG, PNG, and GIFs
$element->addValidator('Extension', false, 'jpg,png,gif');
$form->addElement($element, 'foo');