nginx上传client_max_body_size问题


117

我正在运行nginx / ruby​​-on-rails,并且有一个简单的多部分表单可以上传文件。一切正常,直到我决定限制要上传的文件的最大大小。为此,我将nginx设置client_max_body_size1m(1MB),并期望在该规则中断时作为响应的HTTP 413(请求实体太大)状态。

问题是,当我上载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 / Firefox 3.6.13

Answers:


128

当客户端client_max_body_size通过发送413响应并关闭连接通知客户端将发送大于的正文时,nginx“快速失败” 。

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

如果您的HTTP客户端支持它,则处理此问题的最佳方法是发送Expect: 100-Continue标头。nginx的支持此作为正确的1.2.7,并且将一个应答413 Request Entity Too Large响应而不是100 Continue如果Content-Length超过了最大身体尺寸。


1
哦,我应该指出,此答案假设客户端正在发送Content-Length而不是在发送Transfer-Encoding: chunked
萧伯纳

2
Nginx作者在邮件列表上发布了一个补丁来解决此问题:nginx.2469901.n2.nabble.com/…不过, 是否将其添加到1.2.x稳定分支中没有任何消息。
乔·肖

谢谢,这实际上解释了很多。当然,看起来像是Expect处理大型请求的方式。
2013年

更新了我的回答,以指出我之前提到的补丁已提交并合并到1.2.7版本中。
Joe Shaw 2014年

只是为了节省时间寻找一个很好的语法(就像我花):request.setHeader(HttpHeaders.EXPECT, CONTINUE);import org.apache.http.HttpHeaders;import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
埃雷兹科恩

48

您的上传会在最后消失吗?崩溃前有99%?客户端主体和缓冲区是关键,因为nginx必须缓冲传入的数据。主体配置(请求主体的数据)指定nginx如何处理从多部分形式的客户端到应用程序逻辑的大量二进制数据流。

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

设置body_in_file_onlyclean并调整的缓冲区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;

即使这确实导致nginx返回正确的HTTP 413,UA仍将最终发送整个请求主体,不是吗?在那种情况下,我认为值得尝试@ joe-shaw建议的方法。
2013年

@krukid,看起来我们在NGINX“快速失败”之前完成了99%的上传,我同意你的看法。在这种情况下,请求对象周围的所有迹象都是肯定的,即,诊断是内部服务器应用程序逻辑很好-无论运行在Nginx后面。因此,虽然请求的格式很可能很合理,但我们需要考虑的是NGINX为什么在响应中令人窒息。client_max_body_size应该是我们首先要考虑的配置选项,然后考虑缓冲区,因为上传足够大的正确解决方案取决于服务器也可以处理多少内存。
Bent Cardan

@本·卡丹(Bent Cardan)。这种方法似乎是更好的方法,我尝试过。但是对于4mb文件,大约20秒后我仍然出现413错误。我的上行速度无法在20秒内管理4 MB,所以这是在数据流了很长时间之后发生的。有什么想法吗?
Jerome 2014年

我在nginx.conf文件_client_max_body_size 300M中添加了更改;sendfile on; send_timeout 300s; _它对我而言非常有效谢谢
Ramesh Chand

解决方案对我有效openshift php7 nginx
2016年

7

文档中

有必要记住,浏览器不知道如何正确显示此错误。

我怀疑这是正在发生的事情,如果您使用FirebugLive HTTP Headers(均为Firefox扩展)之类的工具来回检查HTTP,您将能够看到实际情况。


1
我在这里也遇到过这个问题:forum.nginx.org/read.php?2,2620 nginx作者说,人们可以尝试更改lingering_time / lingering_timeout,这对我来说都不起作用。此外,当我上传1.2MB的文件(限制为1MB)并轻松建立稳定的5Mbps连接时,我只是看不到持久的超时问题。我已经嗅出了响应,它确实发送了带有“ Connection:close”标头的413页,但是连接似乎没有关闭。
2011年

我想我很难相信,即使存在一个完全有效的413 HTTP状态,它也不会在浏览器中触发。我在很多地方搜寻了人们无法摆脱的页面,甚至从未见过。
2011年

如果禁用乘客,是否会关闭连接?
马克·罗斯

好吧,我比较了有和没有乘客的情况。当一切正常运行并且我上传的文件比1MB的限制大几倍(〜14MB)时,我得到413次响应(因为客户端一直在发送数据块),最后的“连接重置”确实看起来像是超时。没有乘客,我会收到一个413即时响应,并且所有进度都停止了,但是我仍然看到“连接重置”页面,而不是我的静态413.html或任何暗示“实体太大”的内容
krukid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.