首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 大檔案上傳配置完整指南:突破 8MB 限制的關鍵參數與架構優化

     編輯:PHP 相關知識

核心 php.ini 參數詳解

預設 PHP 限制上傳 2MB,實務中常需上傳數百 MB 甚至 GB 級檔案。需協調調整以下四組關鍵參數:

參數預設值建議大值說明
file_uploadsOnOn啟用 HTTP 檔案上傳
upload_max_filesize2M100M~2G單一檔案最大值
post_max_size8M> upload_max_filesizePOST 總資料大小,需大於檔案上限
upload_tmp_dir系統預設/var/tmp/uploads暫存目錄,需可寫、空間足夠、非 Web 可讀

執行階段限制參數

大檔案上傳耗時久,必須放寬執行時間與記憶體限制:

參數預設值建議值影響
max_execution_time300 (無限制) 或 3600腳本最大執行秒數
max_input_time600 或 3600解析輸入資料最大秒數 (含上傳)
memory_limit128M256M~512M腳本記憶體上限,分塊處理可較低

Web Server 層面配置

Nginx (nginx.conf)

http {
    client_max_body_size 2G;        # 客戶端請求體最大值
    client_body_timeout 300s;       # 讀取請求體超時
    proxy_read_timeout 300s;        # 代理讀取超時
    proxy_send_timeout 300s;        # 代理發送超時
    
    # 快取區域 (選用)
    client_body_temp_path /var/tmp/nginx/client_body 1 2;
}

Apache (httpd.conf / .htaccess)

LimitRequestBody 2147483648  # 2GB (bytes)
TimeOut 300
# mod_security 可能需調整
SecRequestBodyLimit 2147483648
SecRequestBodyInMemoryLimit 1048576

PHP 程式碼層面最佳實務

1. 分塊處理避免記憶體爆炸

function handleLargeUpload($tmpPath, $destPath, $chunkSize = 1024 * 1024) {
    $src = fopen($tmpPath, 'rb');
    $dst = fopen($destPath, 'wb');
    while (!feof($src)) {
        fwrite($dst, fread($src, $chunkSize));
    }
    fclose($src);
    fclose($dst);
    return true;
}

2. 斷點續傳/分片上傳架構

// 前端切片 (如使用 Uppy, Resumable.js, Dropzone)
// 後端合併端點
function mergeChunks($uploadId, $totalChunks, $finalName) {
    $chunkDir = "/tmp/chunks/$uploadId/";
    $finalPath = "/uploads/$finalName";
    $fp = fopen($finalPath, 'wb');
    for ($i = 1; $i <= $totalChunks; $i++) {
        $chunkFile = $chunkDir . $i;
        if (!file_exists($chunkFile)) return false;
        fwrite($fp, file_get_contents($chunkFile));
        unlink($chunkFile); // 釋放空間
    }
    fclose($fp);
    rmdir($chunkDir);
    return true;
}

3. 串流式驗證 (邊上傳邊檢查)

// 使用 php://input 串流 (需搭配前端直接 POST 二進位)
// 注意:此模式下 $_FILES 不會自動填入
$input = fopen('php://input', 'rb');
$hash = hash_init('sha256');
$size = 0;
while (!feof($input)) {
    $chunk = fread($input, 8192);
    hash_update($hash, $chunk);
    $size += strlen($chunk);
    if ($size > MAX_SIZE) throw new Exception('超過大小限制');
    // 可即時寫入目的地或驗證 MIME (需緩衝頭部)
}
fclose($input);

常見問題排查表

現象可能原因解決方向
上傳無反應、白頁post_max_size 過小調大 post_max_size > upload_max_filesize
$_FILES 為空表單缺 enctype、或 Nginx client_max_body_size 過小檢查表單屬性、Nginx 配置
上傳中斷 (504/502)proxy_read_timeout 過短增加 Nginx/Apache 超時設定
暫存目錄空間不足upload_tmp_dir 分區太小掛載大磁碟、或改用串流直寫
記憶體耗盡memory_limit 過小、或未分塊處理分塊讀寫、避免 file_get_contents 大檔案

現代化架構建議

  1. 前端直傳雲端儲存:預簽名 URL 直傳 S3/OSS/GCS,完全繞過應用伺服器
  2. 分片上傳標準化:採用 Resumable.js 或 Uppy 前端庫,後端實作 tus.io 協定
  3. 非同步處理管線:上傳完成發送訊息至佇列 (RabbitMQ/Kafka),背景處理轉碼、掃毒、索引
  4. 監控與告警:記錄上傳成功率、平均速度、失敗原因分布,設定異常告警

總結

大檔案上傳非單一參數調整即可解決,需從 PHP、Web Server、網路基礎設施、前端體驗、後端架構全鏈路優化。現代專案強烈建議採用雲端直傳 + 分片上傳 + 非同步處理架構,將上傳壓力從應用層剝離。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved