2011-02-09 97 views
99

我正在运行nginx/ruby​​-on-rails,我有一个简单的multipart表单来上传文件。 一切工作正常,直到我决定限制我想上传的文件的最大大小。为此,我将nginx client_max_body_size设置为1m(1MB),并且在该规则中断时预期HTTP 413(请求实体太大)状态作为响应。nginx上传client_max_body_size问题

问题是当我上载一个1.2 MB的文件,而不是显示HTTP 413错误页面时,浏览器挂起一点,然后死亡与“连接被重置,而页面加载”消息。

我试过几乎每个选项都有nginx提供,似乎没有任何工作。有没有人对此有任何想法?

这里是我的nginx.conf:

worker_processes 1; 
timer_resolution 1000ms; 
events { 
    worker_connections 1024; 
} 

http { 
    passenger_root /the_passenger_root; 
    passenger_ruby /the_ruby; 

    include  mime.types; 
    default_type application/octet-stream; 

    sendfile   on; 
    keepalive_timeout 65; 

    server { 
     listen 80; 
     server_name www.x.com; 
     client_max_body_size 1M; 
     passenger_use_global_queue on; 
     root /the_root; 
     passenger_enabled on; 

     error_page 404 /404.html; 
     error_page 413 /413.html;  
    }  
} 

感谢。


**Edit**

环境/ UA:的Windows XP /火狐3.6.13

回答

109

当客户端发送一个大于client_max_body_size的主体时,通过发送一个413响应并关闭连接,nginx会“快速失败”。

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

如果您的HTTP客户端支持它,处理此问题的最佳方法是发送一个Expect: 100-Continue标头。 Nginx自1.2.7开始正确支持此功能,并且如果Content-Length超出最大主体大小,将会回复413 Request Entity Too Large响应,而不是100 Continue

7

the documentation

有必要记住的是,浏览器做不知道如何正确显示这个错误。

我怀疑这是发生了什么,如果你检查HTTP进行往复使用的工具,如FirebugLive HTTP Headers(包括Firefox扩展),你可以看到什么是真正回事。

+1

我遇到,在这里,太:http://forum.nginx.org/read.php?2,2620凡nginx的作者说,人们可以尝试改变lingering_time/lingering_timeout - 这两者有在我的情况下没有效果。另外,我只是看不到持续的超时问题,当我上传1.2MB的文件时,只有1MB的限制,很容易有稳定的5Mbps连接。我嗅探了响应,它确实发送了“Connection:close”标题的413页面,但连接似乎没有关闭。 – krukid 2011-02-10 11:19:54

+0

我想我只是很难相信,即使有一个完全有效的413 HTTP状态,它不会在浏览器中触发。我搜索了很多地方,人们无法摆脱那个页面,我从来没有看到它。 – krukid 2011-02-10 11:29:30

+0

如果您禁用乘客,是否关闭连接? – 2011-02-10 15:23:27

41

你的上传死在最后?碰撞前99%?客户端主体和缓冲区是关键,因为nginx必须缓冲传入的数据。主体配置(请求主体的数据)指定nginx如何处理来自多部分形式客户端的二进制数据批量流到您的应用逻辑。

clean设置通过指示nginx将传入的缓冲区存储在文件中,然后通过删除它从磁盘清理该文件来释放内存和消耗限制。

body_in_file_only设置为clean并调整client_max_body_size的缓冲区。原问题的配置已经有了sendfile,也增加了超时。我使用下面的设置来解决这个问题,适用于您的本地配置,服务器,http上下文中的&。

client_body_in_file_only clean; 
client_body_buffer_size 32K; 

client_max_body_size 300M; 

sendfile on; 
send_timeout 300s;