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

PHP下載遠程文件到本地:file_get_contents vs cURL 兩種方案完整對比

     編輯:PHP 相關知識

遠程文件下載:從簡單到健壯的工程化實踐

常見需求:抓取遠程圖片/文件存入本地服務器(如采集、鏡像、遷移)。本文提供兩種方案並分析優劣。

方案一:file_get_contents(簡單、適合小文件)

<?php
function downloadWithFGC(string $url, string $saveDir = '.'): ?string {
    $content = @file_get_contents($url);
    if ($content === false) return null;
    $ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: '.bin';
    $filename = $saveDir . '/' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . $ext;
    if (file_put_contents($filename, $content) === false) return null;
    return $filename;
}

缺點:無超時控制、無重試、無進度、大文件佔用記憶體(一次性讀入)、無法處理重定向/認證/斷點續傳。

方案二:cURL 流式寫入(生產環境推薦)

<?php
function downloadWithCurl(string $url, string $saveDir = '.', array $options = []): ?string {
    $defaults = [
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Downloader)',
    ];
    $ch = curl_init($url);
    curl_setopt_array($ch, $defaults + $options);

    // 獲取文件名
    $ext = '.bin';
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($ch, $header) use (&$ext) {
        if (stripos($header, 'Content-Disposition:') === 0) {
            if (preg_match('/filename=["\']?([^"\';]+)/i', $header, $m)) {
                $ext = pathinfo($m[1], PATHINFO_EXTENSION) ? '.' . pathinfo($m[1], PATHINFO_EXTENSION) : $ext;
            }
        } elseif (stripos($header, 'Content-Type:') === 0) {
            $mime = trim(substr($header, 13));
            $extMap = ['image/jpeg'=>'.jpg','image/png'=>'.png','image/gif'=>'.gif','application/pdf'=>'.pdf'];
            $ext = $extMap[$mime] ?? $ext;
        }
        return strlen($header);
    });

    $filename = $saveDir . '/' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . $ext;
    $fp = fopen($filename, 'wb');
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192);

    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    fclose($fp);

    if ($result === false || $httpCode >= 400) {
        @unlink($filename);
        return null;
    }
    return $filename;
}

進階:大文件斷點續傳(Range 請求)

function downloadResumable(string $url, string $dest, int $chunkSize = 1024*1024): bool {
    $fileSize = filesize($dest) ?? 0;
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RANGE => $fileSize . '-',
        CURLOPT_FILE => fopen($dest, 'ab'),
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT => 300,
    ]);
    $result = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return $result !== false && ($code === 200 || $code === 206);
}

方案選型表

安全提醒

  • 驗證 MIME 類型與副檔名一致,防止上傳惡意腳本偽裝圖片。
  • 限制下載域名白名單,防 SSRF 攻擊。
  • 設置 open_basedir 限制寫入目錄。
  • 定期清理臨時文件,防止磁盤佔滿。

掌握 cURL 完整參數,是 PHP 開發者處理網絡 I/O 的核心基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦方案關鍵參數
小圖標/配置文件 (<1MB)file_get_contentsallow_url_fopen=On
大文件/視頻/安裝包cURL 流式CURLOPT_BUFFERSIZE, CURLOPT_WRITEFUNCTION
需認證/重定向/斷點續傳cURL 完整參數CURLOPT_RANGE, CURLOPT_COOKIE, CURLOPT_HTTPHEADER
高併發采集cURL 多線程curl_multi_* 系列