2011-02-09 78 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;