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

PHP cURL 實戰速查手冊:從基礎 GET/POST 到 JSON API、代理、FTP、異步並發

     編輯:PHP 相關知識

cURL 是 PHP 與外部 HTTP/網絡服務交互的瑞士軍刀

本文匯總 8 大高頻場景的最小可用代碼片段,涵蓋基礎請求、健康檢查、替代 file_get_contents、圖片批量下載、FTP 上傳、JSON API 調用、代理穿透、異步並發,並附帶錯誤處理與安全最佳實踐。

通用初始化模板

function curl_init_common(string $url, array $options = []): resource {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER         => false,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 5,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_SSL_VERIFYPEER => true,  // 生產環境務必開啟
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; PHP-cURL)',
    ] + $options);
    return $ch;
}

場景 1:基礎 GET 請求(含代理)

$ch = curl_init_common('https://api.example.com/users');
curl_setopt($ch, CURLOPT_PROXY, 'https://proxy:3128'); // 可選
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'user:pass');  // 可選
$response = curl_exec($ch);
if ($response === false) throw new Exception(curl_error($ch), curl_errno($ch));
$data = json_decode($response, true);
curl_close($ch);

場景 2:健康檢查(僅 HEAD,不下載 Body)

function isUp(string $url): bool {
    $ch = curl_init_common($url);
    curl_setopt_array($ch, [
        CURLOPT_NOBODY       => true,   // HEAD 請求
        CURLOPT_CUSTOMREQUEST => 'HEAD',
    ]);
    $ok = curl_exec($ch) !== false && curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
    curl_close($ch);
    return $ok;
}

場景 3:替代 file_get_contents(支援 HTTPS、超時、重定向)

function http_get(string $url): string|false {
    $ch = curl_init_common($url);
    $data = curl_exec($ch);
    curl_close($ch);
    return $data;
}

場景 4:POST JSON API(含簽名/Token)

$payload = json_encode(['order_id' => 12345, 'amount' => 99.9]);
$ch = curl_init_common('https://pay.example.com/api/charge');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Content-Length: ' . strlen($payload),
        'Authorization: Bearer ' . $accessToken,
    ],
]);
$resp = curl_exec($ch);

場景 5:multipart/form-data 文件上傳

$ch = curl_init_common('https://api.example.com/upload');
$cfile = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'avatar.jpg');
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $cfile, 'user_id' => 100]);
$resp = curl_exec($ch);

場景 6:FTP 上傳/下載

// 上傳
$fp = fopen('/local/path/file.txt', 'r');
$ch = curl_init('ftp://user:pass@ftp.example.com/remote/file.txt');
curl_setopt_array($ch, [
    CURLOPT_UPLOAD      => true,
    CURLOPT_INFILE      => $fp,
    CURLOPT_INFILESIZE  => filesize('/local/path/file.txt'),
    CURLOPT_FTPASCII    => true, // 文本模式
]);
curl_exec($ch);
fclose($fp);
curl_close($ch);

場景 7:異步並發請求(curl_multi)

function curl_multi_fetch(array $urls, int $maxConcurrent = 10): array {
    $mh = curl_multi_init();
    $handles = [];
    $results = [];

    // 初始化所有 handle
    foreach ($urls as $i => $url) {
        $ch = curl_init_common($url);
        $handles[$i] = $ch;
        curl_multi_add_handle($mh, $ch);
    }

    $running = null;
    do {
        curl_multi_exec($mh, $running);
        curl_multi_select($mh, 0.1); // 等待活動
        while ($info = curl_multi_info_read($mh)) {
            $ch = $info['handle'];
            $idx = array_search($ch, $handles, true);
            $results[$idx] = [
                'code'    => curl_getinfo($ch, CURLINFO_HTTP_CODE),
                'body'    => curl_multi_getcontent($ch),
                'error'   => curl_error($ch),
                'errno'   => curl_errno($ch),
            ];
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }
    } while ($running);

    curl_multi_close($mh);
    return $results;
}

// 使用
$urls = ['https://api.a.com', 'https://api.b.com', 'https://api.c.com'];
$results = curl_multi_fetch($urls, 5);

場景 8:批量下載圖片(帶斷點續傳邏輯)

function downloadImages(array $urls, string $dir): void {
    if (!is_dir($dir)) mkdir($dir, 0755, true);
    $mh = curl_multi_init();
    $handles = [];

    foreach ($urls as $url) {
        $filename = $dir . '/' . basename(parse_url($url, PHP_URL_PATH));
        if (file_exists($filename)) continue; // 簡易斷點
        $fp = fopen($filename, 'w');
        $ch = curl_init_common($url);
        curl_setopt_array($ch, [CURLOPT_FILE => $fp, CURLOPT_BINARYTRANSFER => true]);
        $handles[$url] = ['ch' => $ch, 'fp' => $fp];
        curl_multi_add_handle($mh, $ch);
    }

    $running = null;
    do {
        curl_multi_exec($mh, $running);
        curl_multi_select($mh, 0.1);
        while ($info = curl_multi_info_read($mh)) {
            $ch = $info['handle'];
            foreach ($handles as $url => $h) {
                if ($h['ch'] === $ch) {
                    fclose($h['fp']);
                    curl_multi_remove_handle($mh, $ch);
                    curl_close($ch);
                    unset($handles[$url]);
                    break;
                }
            }
        }
    } while ($running);
    curl_multi_close($mh);
}

錯誤處理黃金法則

  1. 永遠檢查 curl_exec() === false,而非 !$response(空字符串也是合法響應)。
  2. 使用 curl_errno() / curl_error() 獲取具體錯誤。
  3. 關鍵業務記錄 curl_getinfo() 中的 total_time, namelookup_time, connect_time 等指標。
  4. 生產環境嚴禁 CURLOPT_SSL_VERIFYPEER => false,應部署正規 CA 證書或使用 CURLOPT_CAINFO 指定信任鏈。

性能優化清單

  • 復用連接:長運行進程(Swoole/Workerman)中保持 curl_handle 池。
  • 啟用 HTTP/2:CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0。
  • DNS 緩存:CURLOPT_DNS_CACHE_TIMEOUT => 600。
  • 超時拆分:連接超時 CURLOPT_CONNECTTIMEOUT、總超時 CURLOPT_TIMEOUT 分開設置。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved