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

PHP cURL 從入門到精通:GET/POST、檔案上傳下載、JSON API、代理、認證、錯誤處理全景指南

     編輯:PHP 相關知識

為什麼選擇 cURL 而非 file_get_contents?

能力file_get_contentscURL
HTTP 方法僅 GETGET/POST/PUT/DELETE/HEAD/PATCH 任意
自定義 Header需 stream context,繁瑣CURLOPT_HTTPHEADER 直觀
Cookie 管理極難CURLOPT_COOKIEJAR/FILE 自動
檔案上傳不支援CURLOPT_POSTFIELDS + CURLFile
斷點續傳/大檔下載全量載入記憶體CURLOPT_WRITEFUNCTION 邊寫邊收
代理/認證/SSL不支援/極難完整支援
錯誤細節僅 true/falsecurl_errno()/curl_error()/curl_getinfo()
並發請求不支援curl_multi_* 原生支援

四步核心流程

<?php
$ch = curl_init();                          // 1. 初始化
curl_setopt_array($ch, [                    // 2. 設定選項(陣列批量更優雅)
    CURLOPT_URL            => 'https://api.example.com/users',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 5,
    CURLOPT_TIMEOUT        => 10,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_USERAGENT      => 'MyApp/1.0 (+https://example.com)',
    CURLOPT_SSL_VERIFYPEER => true,         // 生產環境必開
    CURLOPT_SSL_VERIFYHOST => 2,
]);
$response = curl_exec($ch);                 // 3. 執行
if ($response === false) {                  // 4. 錯誤處理(注意 ===)
    throw new \RuntimeException('cURL error: ' . curl_error($ch), curl_errno($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);                            // 釋放資源

實戰場景代碼庫

1. POST 表單 / JSON API

<?php
// 表單
$postData = ['name' => 'John', 'action' => 'submit'];
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));

// JSON API
$jsonData = json_encode(['site' => 'example', 'url' => 'https://example.com']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($jsonData),
]);

2. 檔案上傳(現代 CURLFile 寫法,PHP 5.5+)

<?php
$filePath = '/path/to/image.jpg';
$postFields = [
    'file' => new CURLFile($filePath, 'image/jpeg', 'avatar.jpg'),
    'user_id' => 123,
];
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
// 注意:使用 CURLFile 時 CURLOPT_SAFE_UPLOAD 預設 true,無需額外設定

3. 大檔案下載:邊收邊寫,不佔記憶體

<?php
$url = 'https://speed.hetzner.de/100MB.bin';
$dest = '/tmp/100MB.bin';

$fp = fopen($dest, 'wb');
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_FILE        => $fp,           // 直接寫入檔案指標
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT     => 0,             // 無超時
    CURLOPT_NOPROGRESS  => false,
    CURLOPT_PROGRESSFUNCTION => function ($ch, $dlTotal, $dlNow) {
        if ($dlTotal > 0) {
            printf("\rProgress: %.2f%% (%d/%d MB)", $dlNow/$dlTotal*100, $dlNow/1e6, $dlTotal/1e6);
        }
    },
]);
curl_exec($ch);
curl_close($ch);
fclose($fp);

4. HTTP Basic / Bearer Token 認證

<?php
// Basic Auth
curl_setopt($ch, CURLOPT_USERPWD, 'username:password');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

// Bearer Token (JWT 等)
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $accessToken,
]);

5. 代理與 Tunnel

<?php
curl_setopt($ch, CURLOPT_PROXY, 'https://proxy.example.com:3128');
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'proxyUser:proxyPass');
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); // 或 SOCKS5
// HTTPS 經 HTTP 代理需 CURLOPT_HTTPPROXYTUNNEL => true

6. 並發請求

<?php
$urls = [
    'https://api1.example.com',
    'https://api2.example.com',
    'https://api3.example.com',
];

$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_multi_add_handle($mh, $ch);
    $handles[$url] = $ch;
}

$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh); // 等待活動
} while ($running > 0);

$results = [];
foreach ($handles as $url => $ch) {
    $results[$url] = [
        'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
        'body' => curl_multi_getcontent($ch),
        'error' => curl_error($ch),
    ];
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}
curl_multi_close($mh);

進階技巧與避坑指南

  1. 啟用 CURLOPT_SSL_VERIFYPEER: 生產環境必須驗證憑證;僅測試環境臨時關閉並加註釋。
  2. 使用 curl_setopt_array: 批量設定更乾淨,避免重複 curl_setopt。
  3. 錯誤判斷用 === false: 空字串 "" 也是合法回應,== false 會誤判。
  4. 獲取詳細資訊: curl_getinfo($ch) 回傳關聯陣列,含 http_code、total_time、namelookup_time、connect_time、download_content_length 等,極利於效能分析。
  5. 自定義寫入回調: CURLOPT_WRITEFUNCTION 可實現流式處理、進度條、多檔案分流。
  6. 重用 Handle: 同一執行緒內多次請求同域名,保持 $ch 並用 curl_setopt($ch, CURLOPT_URL, $newUrl) 切換,節省 TCP/SSL 握手開銷。
  7. User-Agent 必設: 許多 CDN/WAF 攔截空 UA,設定可識別的應用標識。

除錯三板斧

<?php
// 1. 詳細資訊
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'rw+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// 執行後
rewind($verbose);
echo stream_get_contents($verbose);

// 2. 命令列等效
// curl -v -H "User-Agent: MyApp" "https://api.example.com"

// 3. PHP 內建調試
// php -r 'var_dump(curl_version());'

總結

cURL 是 PHP 與外部世界溝通的瑞士刀。掌握 curl_setopt_array、CURLFile、CURLOPT_WRITEFUNCTION、curl_multi 這幾大核心,配合嚴格錯誤處理與 SSL 驗證,即可構建健壯、高效、可觀測的 HTTP 客戶端。下一步建議學習:Guzzle(物件導向封裝)、Swoole/Workerman 協程 HTTP Client、OpenTelemetry 分散式追蹤整合。

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