最近有一個頁面,要把檔案上傳到 server 上之後,把檔案本身直接轉成 BLOB 後塞到資料庫裡,資料欄位我開成 mediumblob。

`testfile` mediumblob comment '使用者上傳檔案',

小檔案上傳還沒問題,但大檔案上傳遇到一些狀況。首先是 Apache 會吐 HTTP 500 (Internal Server Error)。

我想了一下,在 Apache 的 httpd.conf 把 FastCGI 的 MaxRequestLen 調大一點(我調到 35MB):

MaxRequestLen 36700160

因為發現我在 JavaScript 用 form-data() 組出來的資料,透過 AJAX 傳到後端、而且檔案過大時,$_POST 竟然會變成空的 (empty array),所以 PHP 的設定這邊也要改一下:

post_max_size = 35M
upload_max_filesize = 10M

post_max_size 是指一個頁面 POST 到後端的最大值,要考慮到其他各種欄位;upload_max_filesize 是上傳檔案的大小。在《upload_max_filesize檔案上傳的限制?》這篇有提到,這幾個數值的關係應該是:memory_limit (如果有設定的話) > post_max_size > upload_max_filesize。(我的 memory_limit 在設定這個之前就已經開到 128M 了,所以這次沒有特別調)

這時候網頁可以送出去了,後端程式也接得到檔案了、也能判讀到檔案上限了,不過還是有一個狀況──MySQL 會透過 PDO 傳來檔案太大的抗議:"MySQL server has gone away"

《[MySQL] 解決MySQL server has gone away問題》這篇說,這時候就要調整 MySQL 的 max_allowed_packet 了。

set global max_allowed_packet = 36700160;

(有的文章寫等號後的數值可以直接寫 35MB、35M,我的 MySQL 版本會吐錯誤訊息 "Error Code: 1232. Incorrect argument type to variable 'max_allowed_packet'"。)

我先在查詢視窗裡下了這個指令,不過我沒有重啟 MySQL 服務的權限,重新執行 show variables like '%max_allowed_packet%' 依然顯示舊數值,參考了《MySQL 錯誤 got a packet bigger than 'max_allowed_packet' bytes mysql,裡面提到先透過 command 連上 MySQL 再斷線重連就可以生效。

mysql> quit
C:\> mysql -u root -p

 

我覺得整個過程卡住我最久的是 $_POST 變成空的 Array(),因為從來沒有遇過參數送出後全部被清空的啦!一開始也沒有想到是長度問題,所以還沒注意到 PHP error log 出現 "POST Content-Length of 8939980 bytes exceeds the limit of 8388608 bytes in Unknown" 這樣的文字。(8388608 是預設值,也就是 8MB)

後來馬上加一段 if(count($_POST) == 0) 的判斷式來處理沒有傳到後端時的訊息,提醒自己到時候如果 user 反映這個上限還是不夠用要記得來調 post_max_size。

arrow
arrow

    小攻城師 發表在 痞客邦 留言(0) 人氣()