在導出 Excel、同步遠端資源等場景中,下載大檔案時的記憶體佔用至關重要。本文比較三種常見寫法。
fopen() / file_get_contents() 直接讀取$url = 'https://example.com/large.xls';
$fp = fopen($url, 'r');
file_put_contents('./test.xls', $fp);
缺點:整個檔案會先載入記憶體,大檔案易導致 memory_limit 耗盡。
CURLOPT_RETURNTRANSFER$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
file_put_contents('./test.xls', curl_exec($ch));
curl_close($ch);
同樣會將回應內容完整存入記憶體再寫入磁碟,記憶體壓力大。
$fp = fopen('./test.xls', 'w');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp); // 直接輸出至檔案指標
curl_exec($ch);
curl_close($ch);
fclose($fp);
優點:資料以流方式直接寫入檔案,不佔用 PHP 記憶體,支援任意大小檔案。
| 方案 | 記憶體佔用 | 適用場景 |
|---|---|---|
| file_get_contents / fopen | 高(整檔載入) | 小檔案(<10MB) |
| cURL + RETURNTRANSFER | 高(整檔載入) | 中小檔案,需處理回應標頭 |
| cURL + CURLOPT_FILE | 極低(流式) | 大檔案、長時間下載、生產環境 |
實務上,針對大檔案下載強烈建議使用方案三,並搭配 set_time_limit(0) 避免逾時。