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

PHP 獲取遠程圖片並保存本地:readfile + 輸出緩衝 vs cURL 最佳實踐

     編輯:PHP 相關知識

PHP 獲取遠程圖片並保存本地:readfile + 輸出緩衝 vs cURL 最佳實踐

常見需求:采集圖片、鏡像存儲、生成縮略圖。本文對比三種方案優劣,推薦生產環境使用 cURL。

方案一:readfile + ob_get_contents (簡單但有缺陷)

function saveImageOb(string $url, string $filename = ''): string|false {
    if (!$filename) $filename = date('YmdHis') . '.jpg';
    ob_start();
    readfile($url);
    $img = ob_get_contents();
    ob_end_clean();
    return file_put_contents($filename, $img) ? $filename : false;
}

缺點:無超時控制、無重試、無法設置 User-Agent/Referer、大文件佔用 PHP 內存 (ob 緩衝)、無法獲取 HTTP 狀態碼判斷 404/403。

方案二:file_get_contents + stream_context (略強)

function saveImageStream(string $url, string $filename = ''): string|false {
    $ctx = stream_context_create(['http' => ['timeout' => 10, 'ignore_errors' => true]]);
    $img = @file_get_contents($url, false, $ctx);
    if (!$img) return false;
    return file_put_contents($filename ?: basename($url), $img) ? $filename : false;
}

方案三:cURL (生產級推薦)

function saveImageCurl(string $url, string $savePath, array $options = []): string|false {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_TIMEOUT => 15,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Image Bot)',
        CURLOPT_SSL_VERIFYPEER => false, // 僅測試
        CURLOPT_FILE => fopen($savePath . '.tmp', 'w'), // 直接寫文件避免內存
    ] + $options);

    $success = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $errno = curl_errno($ch);
    curl_close($ch);

    $fp = fopen($savePath . '.tmp', 'r');
    fclose($fp); // 確保 flush

    if ($success && $httpCode === 200 && $errno === 0) {
        rename($savePath . '.tmp', $savePath);
        return $savePath;
    }
    @unlink($savePath . '.tmp');
    return false;
}

關鍵優勢對比

特性readfile+obstream_contextcURL
超時控制❌✅ 總超時✅ 連接/傳輸分離
重試/重定向❌✅ 重定向✅ 完整控制
自定義 Header❌✅✅
大文件內存高 (全載入)高低 (直接落盤)
錯誤診斷困難一般豐富 (錯誤碼、信息)
並發下載❌❌✅ curl_multi

最佳實踐建議

  1. 生產環境統一使用 cURL 封裝庫 (如 Guzzle)
  2. 下載前 getimagesize($url) 預檢 MIME 與尺寸,避免垃圾文件
  3. 臨時文件 .tmp + rename 保證原子性
  4. 異步隊列 (Redis/RabbitMQ + Worker) 處理大批量采集
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved