2010-04-18 39 views
1

在我包含圖像之前,哪些PHP腳本技術在檢測遠程圖像是否存在時運行速度最快?我的意思是,我不想下載遠程圖像的所有字節 - 只是足以檢測它是否存在。快速遠程PHP技術檢測圖像404

雖然在主題上,但只是略有偏差,我想下載足夠的字節來確定JPEG的寬度和高度信息。

在我關注的這個系統設計中,速度是非常重要的。

+0

有人暗示我可以和的fsockopen FREAD做到這一點,有8個字節的PNG信息,並且16 JPG信息的字節。只需要知道這些圖像結構。 – Volomike 2010-04-18 01:47:55

+0

使用Curl或套接字將請求標頭髮送到服務器並檢查響應代碼,200 = OK,404 =未找到。 – Ben 2010-04-18 01:52:10

+0

您是否想一次對一個文件/網址執行此操作,還是您有多個網址?你想檢查內容的「魔術」字節,或者甚至從數據中獲取一些信息,即單獨的http頭文件不會做什麼? – VolkerK 2010-04-18 02:05:14

回答

3

我修改了@ Volomike的代碼來獲得寬度。在這裏,你去...

 

function get_image_dim($sURL) { 
    // note that for jpeg you may need to change 300 to a larger value, 
    // as some height/width info is farther out in the header 
    try { 
    $hSock = @ fopen($sURL, 'rb'); 
    if ($hSock) { 
     while(!feof($hSock)) { 
     $vData = fread($hSock, 300); 
     break; 
     } 
     fclose($hSock); 
     if (strpos(' ' . $vData, 'JFIF')>0) { 
     $vData = substr($vData, 0, 300); 
     $asResult = unpack('H*',$vData);   
     $sBytes = $asResult[1]; 
     $width = 0; 
     $height = 0; 
     $hex_width = ''; 
     $hex_height = ''; 
     if (strstr($sBytes, 'ffc2')) { 
      $hex_height = substr($sBytes, strpos($sBytes, 'ffc2') + 10, 4); 
      $hex_width = substr($sBytes, strpos($sBytes, 'ffc2') + 14, 4); 
     } else { 
      $hex_height = substr($sBytes, strpos($sBytes, 'ffc0') + 10, 4); 
      $hex_width = substr($sBytes, strpos($sBytes, 'ffc0') + 14, 4); 
     } 
     $width = hexdec($hex_width); 
     $height = hexdec($hex_height); 
     return array('width' => $width, 'height' => $height); 
     } elseif (strpos(' ' . $vData, 'GIF')>0) { 
     $vData = substr($vData, 0, 300); 
     $asResult = unpack('h*',$vData); 
     $sBytes = $asResult[1]; 
     $sBytesH = substr($sBytes, 16, 4); 
     $height = hexdec(strrev($sBytesH)); 
     $sBytesW = substr($sBytes, 12, 4); 
     $width = hexdec(strrev($sBytesW)); 
     return array('width' => $width, 'height' => $height); 
     } elseif (strpos(' ' . $vData, 'PNG')>0) { 
     $vDataH = substr($vData, 22, 4); 
     $asResult = unpack('n',$vDataH); 
     $height = $asResult[1];   
     $vDataW = substr($vData, 18, 4); 
     $asResult = unpack('n',$vDataW); 
     $width = $asResult[1];   
     return array('width' => $width, 'height' => $height); 
     } 
    } 
    } catch (Exception $e) {} 
    return FALSE; 
} 

因此,使用它,我們有......在Twitter上

 

// jpeg 
$url = 'http://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Quality_comparison_jpg_vs_saveforweb.jpg/250px-Quality_comparison_jpg_vs_saveforweb.jpg'; 
// png 
//$url = 'http://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png'; 
// gif 
//$url = 'http://upload.wikimedia.org/wikipedia/commons/e/e2/Sunflower_as_gif_small.gif'; 

$dim = get_image_dim($url); 
print_r($dim); 
3

運行一個cURL,做了HEAD請求insted的一個完整的GET

我沒有測試這一點,但希望你能明白我的意思:

<?php 
$url = 'http://www.example.com/image.gif'; 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_NOBODY, true); // this is what sets it as HEAD request 
curl_exec($ch); 

if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') { // 200 = OK 
    // image exists .. 
} 

curl_close($ch); 
?> 

有關更多信息,請參閱cURL docuentation捲曲。

+2

這太棒了。這是一個開始。但是,如果我能理解PNG和JPG圖像頭,而不需要這種捲曲技術,我可能能夠一舉解決我的問題和fsockopen/fread。但是,def爲+1。給我看一些有趣的東西,我不知道。 – Volomike 2010-04-18 02:06:38

2

您應該能夠確定JPEG的尺寸而不用加載其全部內容。對於基線JPEG,即非逐行掃描JPEG,請以字節爲單位掃描,直到遇到0xFFC0。跳過接下來的三個字節。接下來的兩個字節表示高度。它們後面還有兩個字節表示寬度。

例如,在 「FF C0 00 11 08 01 DE 02 D0」,01DE表示478的高度和02D0表示的720

1

寬度我發送GET請求包含RANGE header到儘可能限制實際的數據傳輸(遠程服務器可能不符合RANGE請求,但仍值得一試)。無論您使用套接字(直接)還是使用curl來發出請求,它可能沒有多大區別。但是......你永遠不知道沒有基準。對於捲曲在http://docs.php.net/function.curl-setopt

看看了「CURLOPT_RANGE」選項,可能不(「與僅超薄型CPU功率幾個小時,一臺服務器上。」),以符合您的個人資料,但你可能想嘗試處理一次有多個url,即有多個活動連接,只處理那些不會在讀取操作中阻塞的連接。如果限制因素主要是/只有CPU功率...忘記這部分。 插座:在stream_select 捲曲看一看:看curl_multi_exec()

如果捲曲模塊不可用,你還可以使用HTTP URL包裝結合stream_context_create()發送包含Range頭的請求。

看起來您已經知道在收到數據後如何處理數據。

-3

本地存儲圖像。這是非常簡單和有保證的解決方案。

+0

在這種情況下,我的服務器CPU和磁盤空間有限。基本上需要數百個博客才能使用遠程圖像。 – Volomike 2010-04-18 07:02:08

+0

貪婪是致命的罪行之一,@Volomike如果你負擔不起圖像存儲 - 只是不去數百博客。做一個。 – 2010-04-18 07:28:21

+0

這些圖像來自公共領域來源,如維基百科,Flickr和其他CreativeCommons來源。我正在爲他們的客戶請求,在他們超負荷的服務器上這樣做,我們正試圖通過這些博客減少瓶頸。 – Volomike 2010-04-18 08:45:06

0

我認爲以下例程將檢索JPG,GIF和PNG的圖像高度,或者在404或其他圖像類型上返回=== FALSE條件。該例程也使用最少的服務器資源執行此操作,因爲即使添加了字節限制,file_get_contents()路由似乎實際下載了該文件,就像getimagesize()下載該文件一樣。與此相比,您可以看到性能的提升。

這個例程的工作方式是它只從文件下載300個字節。不幸的是,JPEG不像GIF或PNG那樣在文件中將其高度值推得很遠,所以我必須讀取遠遠超出字節數的文件。然後,通過這些字節,它會掃描該頭文件中的JFIF,PNG或GIF,讓我們知道它是哪種文件類型。一旦我們有了,我們就可以在每個例程上使用獨特的例程來解析標題。請注意,JPEG必須首先使用unpack()和H *,然後掃描ffc2或ffc0並進行處理。然而,GIF必須首先使用h *(在那裏有很大差異)解壓()。

此功能是由我創建的試驗和錯誤,可能是錯誤的。我在幾張圖片上運行它,它似乎很好。如果您發現錯誤,請考慮讓我知道。

無論如何,這個系統會讓我確定一個圖像的高度,並丟棄圖像,如果太高,找到另一個。在我發現的任何隨機圖像中,我在HTML的IMG標記中設置了寬度,並自動調整高度 - 但只有在圖像低於某個高度時纔會看起來很好。同樣,它還會執行404檢查以查看由另一個服務器返回給我的映像是否不適用於不再存在或禁止跨站點鏈接的映像。由於我手動將圖像設置爲固定寬度,因此我不在意讀取圖像寬度。你可以調整這個功能,通常只需要看幾個小字節就可以找到圖像寬度。

function getImageHeight($sURL) { 
    try { 
    $hSock = @ fopen($sURL, 'rb'); 
    if ($hSock) { 
     while(!feof($hSock)) { 
     $vData = fread($hSock, 300); 
     break; 
     } 
     fclose($hSock); 
     if (strpos(' ' . $vData, 'JFIF')>0) { 
     $vData = substr($vData, 0, 300); 
     $asResult = unpack('H*',$vData); 
     $sBytes = $asResult[1]; 
     if (strstr($sBytes, 'ffc2')) { 
      $sBytes = substr($sBytes, strpos($sBytes, 'ffc2') + 10, 4); 
     } else { 
      $sBytes = substr($sBytes, strpos($sBytes, 'ffc0') + 10, 4); 
     } 
     return hexdec($sBytes); 
     } elseif (strpos(' ' . $vData, 'GIF')>0) { 
     $vData = substr($vData, 0, 300); 
     $asResult = unpack('h*',$vData); 
     $sBytes = $asResult[1]; 
     $sBytes = substr($sBytes, 16, 4); 
     $sBytes = strrev($sBytes); 
     return hexdec($sBytes); 
     } elseif (strpos(' ' . $vData, 'PNG')>0) { 
     $vData = substr($vData, 22, 4); 
     $asResult = unpack('n',$vData); 
     $nHeight = $asResult[1]; 
     return $nHeight; 
     } 
    } 
    } catch (Exception $e) {} 
    return FALSE; 
}