Evitar o upload de arquivos grandes com nginx

4

Estou atendendo ao meu site usando o Nginx como servidor da web. Eu ofereço funcionalidade de upload para meus usuários (eles estão autorizados a enviar imagens de até 5Mb), então eu tenho a diretiva: client_max_body_size 5M; na configuração do meu servidor. O que eu notei é que, se eu tento carregar qualquer arquivo, o servidor não impede o upload de arquivos maiores. Apenas como exemplo, suponha que eu tente enviar um vídeo muito grande (um filme) de 700Mb. O servidor não rejeita o upload instantaneamente, mas armazena todos os dados (demorando muito e tornando mais lento o servidor) e somente no final do upload ele retorna um erro 413 Request entity too large .

Portanto, a questão é: existe alguma maneira de configurar corretamente o Nginx para bloquear o upload de arquivos grandes quando os dados transmitidos começarem a superar meu client_max_body_size limite?

Acho que seria muito inseguro continuar a produção com minhas configurações reais e não consegui encontrar nada de útil no Google.

Editar:

Estou usando o php e o Symfony2 como backend ...

Edite (de novo):

Isso é o que aparece no meu 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/"'

O mais estranho é que eu estou monitorando meu nginx error.log com tail -f error.log e a mensagem aparece imediatamente quando o upload começa (antes que ele termine). Então o nginx faz algum tipo de verificação preventiva, mas isso não impede / chunk a solicitação de upload ...

Eu também tentei verificar se o php obtém o controle do upload emitindo um echo 'something'; die(); na página que manipula o upload, mas ele não imprimiu nada e não parou a solicitação de upload. Portanto, deve ser nginx ou alguns recursos internos do php que fazem com que todo o upload continue até que seja completamente transmitido ...

outra edição: Aqui está uma visão do meu top (monitoramento nginx e php) quando um upload de arquivo grande está em andamento (nginx fica sobrecarregado):

edite: aqui está minha configuração 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;
    }
}
    
por Luciano Mammino 28.01.2013 / 11:36

2 respostas

3

Informações úteis aqui: link

cito parte da resposta mais interessante (para o meu caso):

Most clients don't read for responses until the entire request body is sent. Because nginx closes the connection the client sends data to the closed socket, causing a TCP RST.

Nesse caso, é apenas um problema do navegador que não afetará (sobrecarregar) o meu servidor web. Parece que se queixa com a minha inspeção de memória que mostrou que tanto o nginx quanto o php-fastcgi não foram realmente sobrecarregados ao fazer upload de um arquivo grande (700mb).

Eu poderia resolver o problema do navegador de várias maneiras, por exemplo:

  • adicione um <input type="hidden" name="MAX_FILE_SIZE" value="5242880" /> no meu formulário
  • use uma página de erro 413 nginx personalizada
por 28.01.2013 / 21:54
0

O que você está usando php ou rails ou algo assim? porque você deve verificar o tamanho antes de fazer o upload.
defina post_max_size e upload_max_filesize como o valor correspondente em arquivo: php.ini

edite: tente escrever algo assim no seu upload

$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');
    
por 28.01.2013 / 11:47