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

PHP 取得遠端檔案大小三種方法:file_get_contents、get_headers、fsockopen 效能與適用場景比較

     編輯:PHP 綜合知識

需在不下載完整檔案的情況下取得遠端檔案大小,常用三種方法:file_get_contents (下載全文)、get_headers (HEAD 請求)、fsockopen (原始 Socket)。本文比較三者原理、程式碼、效能與限制。

方法一:file_get_contents (最簡單、最慢、記憶體最高)

<?php
$url = 'https://example.com/large.zip';
$content = file_get_contents($url); // 下載整個檔案到記憶體
$size = strlen($content);
echo "Size: $size bytes";
  • 優點: 程式碼最少,無需額外設定。
  • 缺點: 必須下載完整內容,大檔案會佔用大量記憶體、耗時久、易觸發 memory_limit。
  • 需求: allow_url_fopen = On

方法二:get_headers (推薦、標準、輕量)

<?php
$url = 'https://example.com/large.zip';
$headers = get_headers($url, true); // 第二參數 true 回傳關聯陣列
$size = $headers['Content-Length'] ?? null;

if ($size !== null) {
    echo "Size: $size bytes (" . round($size/1024/1024, 2) . " MB)";
} else {
    echo "無法取得大小 (可能為分塊傳輸或伺服器不回傳 Content-Length)";
}
  • 優點: 只發送 HEAD 請求,不下載內容,速度快、記憶體極低。
  • 缺點: 部分伺服器不支援 HEAD、或回傳 Transfer-Encoding: chunked 無 Content-Length。
  • 需求: allow_url_fopen = On

方法三:fsockopen (最底層、無需 allow_url_fopen、可處理 HTTPS 需額外處理)

<?php
function get_remote_size($url) {
    $parts = parse_url($url);
    if (empty($parts['host'])) return false;
    
    $host = $parts['host'];
    $port = $parts['port'] ?? ($parts['scheme'] === 'https' ? 443 : 80);
    $path = $parts['path'] ?? '/';
    if (!empty($parts['query'])) $path .= '?' . $parts['query'];
    
    $timeout = 10;
    $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
    if (!$fp) return false;
    
    // HTTP/1.1 需 Host 標頭
    $request = "HEAD $path HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
    fwrite($fp, $request);
    
    while (!feof($fp)) {
        $line = fgets($fp, 1024);
        if (trim($line) === '') break; // 標頭結束
        if (stripos($line, 'Content-Length:') === 0) {
            fclose($fp);
            return (int)trim(substr($line, 15));
        }
    }
    fclose($fp);
    return false;
}

// 使用
$size = get_remote_size('https://example.com/file.zip');
if ($size !== false) echo "Size: $size";
else echo "Failed";
  • 優點: 不依賴 allow_url_fopen,完全控制請求細節,可處理特殊協定。
  • 缺點: 程式碼複雜,HTTPS 需 stream_socket_client + SSL context,錯誤處理繁瑣。
  • 適用: 受限環境、需自定義 User-Agent/Cookie/Proxy。

效能與適用場景比較

指標file_get_contentsget_headersfsockopen
網路流量完整檔案大小~幾百 Bytes~幾百 Bytes
記憶體用量檔案大小極低極低
執行時間下載時間RTT x 1-2RTT x 1-2
支援 HTTPS是是需 SSL context
需 allow_url_fopen是是否
適用大檔案否是是
分塊傳輸支援自動合併無 Content-Length無 Content-Length

進階:處理無 Content-Length 的情況

  • Transfer-Encoding: chunked:無法預知大小,只能下載計算或接受未知。
  • 範圍請求:Range: bytes=0-0 取得 Content-Range: bytes 0-0/123456 解析總大小。
<?php
function get_size_via_range($url) {
    $ctx = stream_context_create(['http' => [
        'method' => 'HEAD',
        'header' => 'Range: bytes=0-0',
    ]]);
    $headers = get_headers($url, true, $ctx);
    if (isset($headers['Content-Range'])) {
        // bytes 0-0/123456
        return (int)substr(strrchr($headers['Content-Range'], '/'), 1);
    }
    return $headers['Content-Length'] ?? null;
}

最佳實踐建議

  1. 首選 get_headers():標準、輕量、PHP 內建。
  2. 受限環境:用 fsockopen 或 stream_socket_client。
  3. 大量並發檢查:使用 curl_multi 非阻塞批次發送 HEAD 請求。
  4. 快取結果:同一 URL 短時間內重複查詢,快取大小避免重複請求。
  5. 錯誤處理:統一捕獲 false/null,記錄日誌、預設值處理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved