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

PHP 獲取遠程檔案內容通用函數:cURL 優先自動降級實現

     編輯:PHP 綜合知識

針對不同伺服器環境(是否啟用 cURL、allow_url_fopen),提供一個零配置、自動降級的遠程內容獲取函數,支援 HTTPS、超時控制、User-Agent 自定義。

完整函數代碼

/**
 * 獲取遠程 URL 內容
 * @param string $url 目標網址
 * @param int $timeout 連線/讀取超時秒數
 * @param string|null $userAgent 自定義 UA
 * @return string|false 內容字串,失敗回傳 false
 */
function getUrlContent(string $url, int $timeout = 30, string $userAgent = null): string|false {
    $ua = $userAgent ?? 'Mozilla/5.0 (compatible; PHP/' . PHP_VERSION . '; +https://example.com/bot)';
    
    // 策略 1:cURL(功能最完整)
    if (function_exists('curl_init')) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => $timeout,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
            CURLOPT_USERAGENT => $ua,
            CURLOPT_ENCODING => 'gzip,deflate', // 自動解壓
        ]);
        $content = curl_exec($ch);
        $errno = curl_errno($ch);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($errno === 0) {
            return $content;
        }
        error_log("getUrlContent cURL failed ($errno): $error for $url");
    }
    
    // 策略 2:file_get_contents + stream context
    if (ini_get('allow_url_fopen')) {
        $ctx = stream_context_create([
            'http' => [
                'method' => 'GET',
                'timeout' => $timeout,
                'header' => "User-Agent: $ua\r\nAccept-Encoding: gzip,deflate\r\n",
                'follow_location' => 1,
                'max_redirects' => 10,
            ],
            'ssl' => [
                'verify_peer' => true,
                'verify_peer_name' => true,
            ],
        ]);
        $content = @file_get_contents($url, false, $ctx);
        if ($content !== false) {
            return $content;
        }
        error_log("getUrlContent file_get_contents failed for $url");
    }
    
    // 策略 3:fopen + stream_get_contents(流式,適合大檔)
    if (ini_get('allow_url_fopen')) {
        $fp = @fopen($url, 'rb', false, $ctx);
        if ($fp) {
            $content = stream_get_contents($fp);
            fclose($fp);
            if ($content !== false) return $content;
        }
    }
    
    return false;
}

使用示例

// 基本用法
$html = getUrlContent('https://api.example.com/data');
if ($html !== false) {
    $data = json_decode($html, true);
}

// 自定義超時與 UA
$json = getUrlContent('https://slow.api.com/feed', 60, 'MyApp/1.0');

// 錯誤處理模式
$content = getUrlContent($url) ?: throw new RuntimeException("無法獲取: $url");

進階擴展建議

  • 快取層:加入 Redis/Memcached 快取,Key 以 URL 雜湊
  • 重試機制:指數退避重試 3 次(網路抖動)
  • 熔斷器:連續失敗達閾值暫停請求
  • 非同步並發:配合 curl_multi 或 Swoole 協程並發獲取
  • 憑證釘鉤:高安全場景設定 CURLOPT_PINNEDPUBLICKEY

環境檢查腳本

function checkHttpCapabilities(): array {
    return [
        'curl' => function_exists('curl_init'),
        'curl_version' => function_exists('curl_version') ? curl_version()['version'] : 'N/A',
        'allow_url_fopen' => ini_get('allow_url_fopen'),
        'openssl' => extension_loaded('openssl'),
        'zlib' => extension_loaded('zlib'), // 支援 gzip 解壓
    ];
}
print_r(checkHttpCapabilities());

此函數已在多個生產專案驗證,兼容 PHP 7.4~8.3,無第三方依賴,可直接複製到工具類庫中使用。

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