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

file_get_contents vs cURL:PHP 抓取遠端內容的正確姿勢

     編輯:PHP 相關知識

核心差異一覽

特性file_get_contentscURL
依賴設定需 allow_url_fopen=On需 curl 擴充套件
HTTP 控制極少(僅 stream context)完整(Header、Cookie、驗證、Proxy...)
錯誤處理回傳 false,需檢查 $http_response_header豐富錯誤碼、詳細資訊
效能簡單 GET 較快複雜請求更穩定
支援協定HTTP、FTP、檔案...HTTP/HTTPS、FTP、SMTP、LDAP 等 20+

何時選擇哪一個?

file_get_contents:簡單的 GET 請求、本地檔案讀取、allow_url_fopen 開啟的環境。
cURL:POST 請求、需設定 Header/Cookie、HTTPS 驗證、Proxy、檔案上傳、超時控制、重試邏輯、生產環境標準選擇。

file_get_contents 進階用法

基本用法

$content = @file_get_contents('https://api.example.com/data');
if ($content === false) {
    // 錯誤處理
}

使用 Stream Context 自訂請求

$options = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\n" .
                    "Authorization: Bearer $token\r\n",
        'content' => json_encode(['key' => 'value']),
        'timeout' => 10,
        'ignore_errors' => true, // 取得 4xx/5xx 回應內容
    ]
];
$context = stream_context_create($options);
$response = file_get_contents('https://api.example.com/endpoint', false, $context);

// 取得 HTTP 狀態碼
if (isset($http_response_header[0])) {
    preg_match('/HTTP\/\d\.\d\s+(\d+)/', $http_response_header[0], $matches);
    $statusCode = (int)$matches[1];
}

cURL 完整實戰範本

通用封裝函數

function curlRequest(string $url, array $options = []): array {
    $ch = curl_init();
    
    $defaults = [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => true,  // 生產環境必須驗證
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_USERAGENT => 'MyApp/1.0 (+https://example.com)',
    ];
    
    curl_setopt_array($ch, $defaults + $options);
    
    $response = curl_exec($ch);
    $errno = curl_errno($ch);
    $error = curl_error($ch);
    $info = curl_getinfo($ch);
    
    curl_close($ch);
    
    return [
        'body' => $response,
        'error' => $errno ? $error : null,
        'errno' => $errno,
        'http_code' => $info['http_code'],
        'content_type' => $info['content_type'],
        'total_time' => $info['total_time'],
    ];
}

常見場景範例

// 1. 簡單 GET
$result = curlRequest('https://api.example.com/users');

// 2. POST JSON
$result = curlRequest('https://api.example.com/users', [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['name' => 'John']),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);

// 3. 檔案上傳 (PHP 5.5+)
$result = curlRequest('https://api.example.com/upload', [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('/path/to/file.jpg', 'image/jpeg', 'photo.jpg'),
    ],
]);

// 4. Basic Auth
$result = curlRequest('https://api.example.com/protected', [
    CURLOPT_USERPWD => 'username:password',
]);

// 5. 設定 Proxy
$result = curlRequest('https://api.example.com/data', [
    CURLOPT_PROXY => 'proxy.example.com:8080',
    CURLOPT_PROXYUSERPWD => 'user:pass',
]);

常見問題排查

現象可能原因解決方案
file_get_contents 回傳 falseallow_url_fopen=Off / 防火牆 / DNS改用 cURL / 檢查 php.ini / 測試網路
cURL error 60: SSL certificate problem缺少 CA 憑證 / 憑證過期設定 CURLOPT_CAINFO / 更新 ca-bundle.crt
中文亂碼編碼不一致檢查 Content-Type charset / 使用 mb_convert_encoding
超時對方伺服器慢 / 網路問題調大 CURLOPT_TIMEOUT / 非同步處理

現代替代方案:Guzzle HTTP Client

生產環境強烈建議使用 Guzzle:

composer require guzzlehttp/guzzle

$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.example.com/users', [
    'json' => ['name' => 'John'],
    'timeout' => 10,
    'headers' => ['Authorization' => 'Bearer token'],
]);
$data = json_decode($response->getBody()->getContents(), true);
  • 支援 Promise/非同步、Middleware、重試策略、測試 Mock
  • 物件導向介面,錯誤處理更優雅

總結建議

  1. 簡單專案、快速原型:file_get_contents + stream context
  2. 生產環境、API 整合、複雜需求:cURL 封裝或 Guzzle
  3. 永遠設定 超時、SSL 驗證、User-Agent
  4. 統一錯誤處理與日誌記錄,便於排查
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved