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

PHP 檢測遠程鏈接/文件是否存在的兩種高效方法:get_headers 與 cURL HEAD

     編輯:PHP 相關知識

輕量級 URL 存活檢測:不下載內容,僅檢查 HTTP 狀態碼

在爬蟲、鏈接驗證、圖片防盜鏈等場景,需快速判斷 URL 是否可訪問(返回 200),避免下載大文件浪費帶寬。PHP 提供兩種原生方案:get_headers() 與 cURL HEAD 請求。

方法一:get_headers() —— 簡潔但有限制

<?php
function urlExistsGetHeaders(string $url): bool {
    // @ 抑制警告,allow_url_fopen=On 時可用
    $headers = @get_headers($url, true);
    if ($headers === false) return false;

    // 支援 HTTP/1.1 200 OK、HTTP/2 200 等格式
    $statusLine = $headers[0] ?? '';
    return (bool)preg_match('~^HTTP/\d\.\d\s+2\d\d~', $statusLine);
}

// 用法
var_dump(urlExistsGetHeaders('https://example.com/image.jpg')); // true/false

優點:代碼極短、無需 cURL 擴展。
缺點:受 allow_url_fopen 限制;無法精細控制超時、代理、SSL 驗證、重定向策略;某些 CDN 返回 403/302 導致誤判。

方法二:cURL HEAD 請求 —— 專業級控制

<?php
function urlExistsCurl(string $url, int $timeout = 5): bool {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_NOBODY        => true,      // HEAD 請求
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,     // 跟隨重定向
        CURLOPT_MAXREDIRS     => 5,
        CURLOPT_CONNECTTIMEOUT => $timeout,
        CURLOPT_TIMEOUT       => $timeout,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_USERAGENT     => 'LinkChecker/1.0',
    ]);
    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $errno = curl_errno($ch);
    curl_close($ch);

    if ($errno) return false; // 網絡層失敗
    return $httpCode >= 200 && $httpCode < 300; // 2xx 視為存在
}

優點:完全可控超時、代理、證書、重定向、User-Agent;支援 FTP/HTTP/HTTPS 協議;可獲取 Content-Length、Content-Type 等元信息。
缺點:依賴 cURL 擴展;代碼稍長。

進階:並發批量檢測(curl_multi)

function batchCheck(array $urls, int $concurrency = 20): array {
    $mh = curl_multi_init();
    $handles = [];
    $results = [];

    foreach ($urls as $i => $url) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_NOBODY => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_CONNECTTIMEOUT => 3,
            CURLOPT_TIMEOUT => 5,
        ]);
        $handles[$i] = $ch;
        curl_multi_add_handle($mh, $ch);
    }

    $running = null;
    do {
        curl_multi_exec($mh, $running);
        curl_multi_select($mh, 0.05);
        while ($info = curl_multi_info_read($mh)) {
            $ch = $info['handle'];
            $idx = array_search($ch, $handles, true);
            $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $errno = curl_errno($ch);
            $results[$urls[$idx]] = ($errno === 0 && $code >= 200 && $code < 300);
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }
    } while ($running);

    curl_multi_close($mh);
    return $results;
}

常見陷阱與對策

現象原因對策
返回 403 Forbidden防盜鏈/UA 檢查設置 CURLOPT_REFERER、CURLOPT_USERAGENT 模擬瀏覽器
返回 301/302 重定向短鏈接/HTTPS 強跳開啟 CURLOPT_FOLLOWLOCATION,檢查最終 CURLINFO_EFFECTIVE_URL
超時/連接重置防火牆/目標限流降低併發、增加超時、使用代理池
HEAD 不支援返回 405服務端禁用 HEAD改用 CURLOPT_CUSTOMREQUEST => 'GET' + CURLOPT_RANGE => '0-0' 僅讀 1 字節

最佳實踐建議

  • 簡單腳本、允許 allow_url_fopen:用 get_headers()。
  • 生產服務、需高可用、支援代理/HTTPS/批量:必用 cURL HEAD + curl_multi。
  • 緩存檢測結果(Redis TTL 10-60 分鐘),避免重複探測觸發目標風控。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved