Php

使用 nginx 防止大文件上傳

  • January 29, 2013

我正在使用 Nginx 作為 Web 伺服器為我的網站提供服務。我向我的使用者提供上傳功能(他們被允許送出高達 5Mb 的圖片),所以我有指令:client_max_body_size 5M;在我的伺服器配置中。我注意到的是,如果我嘗試上傳任何文件,網路伺服器不會阻止上傳更大的文件。舉個例子,假設我嘗試上傳一個 700Mb 的非常大的影片(一部電影)。伺服器不會立即拒絕上傳,但它會緩衝整個數據(花費很長時間並減慢伺服器的速度),並且僅在上傳結束時才會返回413 Request entity too large錯誤。

client_max_body_size所以問題是:當傳輸的數據開始超過我的限制時,有沒有辦法正確配置 Nginx 來阻止大文件上傳?

我認為使用我的實際設置進行生產真的很不安全,而且我在Google上找不到任何有用的東西。

編輯:

我使用 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/"`

奇怪的是,我正在監視我的 nginx error.logtail -f error.log並且在上傳開始時(在結束之前)會立即出現該消息。所以 nginx 進行了某種預防性檢查,但它不會停止/分塊上傳請求……

我還嘗試通過在處理上傳的頁面上發出 a 來驗證 php 是否獲得了上傳的控制權,echo 'something'; die();但它沒有列印出任何內容,也沒有停止上傳請求。所以應該是nginx或者一些php內部讓整個上傳一直持續到完全傳輸…

另一個編輯:top當大文件上傳正在進行時(nginx 過載),這是我的(監控 nginx 和 php)的視圖: top:監控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;
   }
}

這裡有用的資訊:https ://stackoverflow.com/questions/4947107/nginx-upload-client-max-body-size-issue

我引用了最有趣的答案的一部分(就我而言):

在發送整個請求正文之前,大多數客戶端不會讀取響應。由於 nginx 關閉了連接,客戶端向關閉的套接字發送數據,導致 TCP RST。

如果是這樣,那隻是瀏覽器問題,不會影響(超載)我的 Web 伺服器。似乎在抱怨我的記憶體檢查顯示 nginx 和 php-fastcgi 在上傳大型(700mb)文件時並沒有真正超載。

我可以通過多種方式解決瀏覽器問題,例如:

  • <input type="hidden" name="MAX_FILE_SIZE" value="5242880" />在我的表格中添加一個
  • 使用自定義 413 nginx 錯誤頁面

引用自:https://serverfault.com/questions/472996