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

PHP 判斷遠端檔案是否存在的實用函式

     編輯:PHP 相關知識

核心思路

發送 HTTP HEAD 請求(不下載主體),檢查回應狀態碼是否為 200 OK。若伺服器不支援 HEAD,退而使用 GET 並立即關閉連線。

健壯版函式

<?php
/**
 * 檢查遠端檔案是否存在
 * @param string $url 完整 URL
 * @param int $timeout 連線逾時秒數
 * @return bool|array false=不存在/錯誤, array=[size, content-type, last-modified]
 */
function remoteFileExists($url, $timeout = 10) {
    $parsed = parse_url($url);
    if (!$parsed || !isset($parsed['host'])) {
        return false;
    }

    $host = $parsed['host'];
    $path = isset($parsed['path']) ? $parsed['path'] : '/';
    if (!empty($parsed['query'])) {
        $path .= '?' . $parsed['query'];
    }
    $port = isset($parsed['port']) ? $parsed['port'] : (($parsed['scheme'] ?? 'http') === 'https' ? 443 : 80);
    $useSSL = ($parsed['scheme'] ?? '') === 'https';

    $fp = @fsockopen(($useSSL ? 'ssl://' : '') . $host, $port, $errno, $errstr, $timeout);
    if (!$fp) {
        return false;
    }

    stream_set_timeout($fp, $timeout);

    // 先嘗試 HEAD
    $request = "HEAD $path HTTP/1.1\r\n";
    $request .= "Host: $host\r\n";
    $request .= "Connection: Close\r\n\r\n";
    fwrite($fp, $request);

    $headers = '';
    while (!feof($fp)) {
        $line = fgets($fp, 1024);
        $headers .= $line;
        if ($line === "\r\n") break;
    }

    // 解析狀態碼
    if (!preg_match('/HTTP\/\d\.\d\s+(\d{3})/', $headers, $m)) {
        fclose($fp);
        return false;
    }
    $status = (int)$m[1];

    // 若 HEAD 失敗(405/501),改用 GET 但只讀標頭
    if ($status >= 400) {
        fclose($fp);
        $fp = @fsockopen(($useSSL ? 'ssl://' : '') . $host, $port, $errno, $errstr, $timeout);
        if (!$fp) return false;
        stream_set_timeout($fp, $timeout);
        $request = "GET $path HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
        fwrite($fp, $request);
        $headers = '';
        while (!feof($fp)) {
            $line = fgets($fp, 1024);
            $headers .= $line;
            if ($line === "\r\n") break;
        }
        if (!preg_match('/HTTP\/\d\.\d\s+(\d{3})/', $headers, $m)) {
            fclose($fp);
            return false;
        }
        $status = (int)$m[1];
    }

    fclose($fp);

    if ($status !== 200) {
        return false;
    }

    // 擷取有用標頭
    $info = ['size' => null, 'type' => null, 'modified' => null];
    if (preg_match('/Content-Length:\s*(\d+)/i', $headers, $m)) $info['size'] = (int)$m[1];
    if (preg_match('/Content-Type:\s*([^\r\n]+)/i', $headers, $m)) $info['type'] = trim($m[1]);
    if (preg_match('/Last-Modified:\s*([^\r\n]+)/i', $headers, $m)) $info['modified'] = strtotime(trim($m[1]));

    return $info;
}

// 測試
$url = 'https://www.example.com/robots.txt';
$result = remoteFileExists($url);
if ($result) {
    echo "存在!大小: " . ($result['size'] ? number_format($result['size']) . ' bytes' : '未知');
    echo " 類型: " . ($result['type'] ?? '未知');
} else {
    echo "不存在或無法存取";
}
?>

進階替代方案

  • cURL:功能更豐富,支援並發、重導向追蹤、憑證驗證。
    function remoteFileExistsCurl($url) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_NOBODY => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false, // 生產環境請設 true 並配置 CA
            CURLOPT_HEADER => true,
            CURLOPT_RETURNTRANSFER => true,
        ]);
        curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $code === 200;
    }
  • get_headers():PHP 內建,簡潔但無法精細控制逾時與 SSL。
    $headers = @get_headers($url, 1);
    return $headers && strpos($headers[0], '200') !== false;

注意事項

  • 大量檢查時請加入延遲或使用非同步並發(cURL multi / Swoole / ReactPHP)。
  • 尊重目標站 robots.txt 與速率限制,避免被封禁。
  • CDN/雲端儲存可能回傳 302 重導向,需啟用 FOLLOWLOCATION。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved