Запрет загрузки большого файла с помощью 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 перегружается):вверху: мониторинг 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;
    }
}

2 ответа

Полезная информация здесь: 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 или рельсы или что-то? потому что вы должны проверить размер перед загрузкой.
установите 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');
Другие вопросы по тегам