使用 nginx 防止大文件上传

使用 nginx 防止大文件上传

我使用 Nginx 作为 Web 服务器来为我的网站提供服务。我为用户提供上传功能(他们可以提交最大 5Mb 的图片),因此我client_max_body_size 5M;在服务器配置中设置了指令:。我注意到,如果我尝试上传任何文件,Web 服务器不会阻止上传更大的文件。举个例子,假设我尝试上传一个 700Mb 的超大视频(电影)。服务器不会立即拒绝上传,而是缓冲整个数据(耗时太长,导致服务器速度变慢),并且仅在上传结束时才返回错误413 Request entity too large

所以问题是:当传输的数据开始超出我的client_max_body_size限制时,有没有什么方法可以正确配置 Nginx 来阻止大文件上传?

我认为使用我的实际设置进行生产确实不安全,而且我在谷歌上找不到任何有用的信息。

编辑:

我正在使用 php 和 Symfony2 作为后端...

编辑(再次):

这是我的错误日志中出现的内容:

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/"`

奇怪的是,我正在error.log用nginx 监控tail -f error.log,上传开始时(在结束之前)会立即出现消息。因此,nginx 会进行某种预防性检查,但不会停止/分块上传请求...

我还尝试通过在页面上发布处理上传的命令来验证 php 是否获得了上传的控制权,echo 'something'; die();但它没有打印出任何内容,也没有停止上传请求。所以应该是 nginx 或一些 php 内部机制使整个上传过程继续进行,直到完全传输完毕...

top另一项编辑:这是正在进行大文件上传(nginx 过载)时 的视图(监控 nginx 和 php):顶部:监控 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;
    }
}

答案1

有用的信息在这里:https://stackoverflow.com/questions/4947107/nginx-upload-client-max-body-size-issue

我引用了最有趣的答案的一部分(就我的情况而言):

大多数客户端在发送完整个请求主体之前不会读取响应。由于 nginx 关闭连接,客户端会将数据发送到已关闭的套接字,从而导致 TCP RST。

如果是这样,那只是浏览器问题,不会影响(超载)我的 Web 服务器。它似乎对我的内存检查有异议,内存检查显示,在上传大型文件(700mb)时,nginx 和 php-fastcgi 都没有真正超载。

我可以用几种方法解决浏览器问题,例如:

  • <input type="hidden" name="MAX_FILE_SIZE" value="5242880" />在我的表单中添加
  • 使用自定义 413 nginx 错误页面

答案2

您使用的是 php 还是 rails 还是其他什么?因为您应该在上传之前检查大小。
设置帖子最大大小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');

相关内容