使用 nginx 防止大文件上传

Luc*_*ino 5 php nginx limitations upload

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

所以问题是:有没有办法正确配置Nginx,以在传输的数据开始超过我的client_max_body_size限制时阻止大文件上传?

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

编辑:

我使用 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/"`
Run Code Online (Sandbox Code Playgroud)

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

我还尝试通过在处理上传的页面上发出 a 来验证 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Luc*_*ino 3

这里有用的信息:/sf/ask/346297521/

我引用了最有趣的答案的一部分(针对我的情况):

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

如果是这样,这只是浏览器问题,不会影响(过载)我的网络服务器。它似乎抱怨我的内存检查显示 nginx 和 php-fastcgi 在上传大(700mb)文件时并没有真正过载。

我可以通过多种方式解决浏览器问题,例如:

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