我使用 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):
编辑:这是我的 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');