Image 404 Algılama için Hızlı Uzaktan PHP Tekniği

6 Cevap php

Ne PHP komut tekniği ben resim eklemek önce uzak bir görüntü yoksa saptanmasında hızlı çalışır? Varsa algılamak için yeterli - Yani, Ben uzaktan kumanda görüntünün tüm bayt indirmek istiyorum değilsiniz.

Ve konuyla ilgili ama sadece hafif bir sapma ile yaparken, ben bir JPEG genişlik ve yükseklik bilgilerini belirlemek için yeterli bayt indirmek istiyorum.

Hız Bu sistem tasarımı üzerinde çalışıyorum burada benim endişe çok önemlidir.

6 Cevap

Ben de genişliğini almak için @ Volomike kodunu modifiye ettik. Buyrun ...


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;
}

Yani, bunu kullanarak biz ...


// 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);

Run a cURL bir HEAD isteği tam bir GET insted yok

Ben bu test etmedi, ama umarım fikir alırsınız:

<?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 cURL hakkında daha fazla bilgi için bkz.

Bunu tüm içeriğini yükleme olmadan bir JPEG boyutlarını belirlemek gerekir. Bazal JPEG için, size 0xFFC0 rastlamak kadar bayt tarama, non-progresif tarama JPEG olduğunu. Önümüzdeki üç bayt atlayın. Sonraki iki bayt yüksekliğini gösterir. Onlar genişliğini belirtmek iki bayt tarafından takip edilmektedir.

Örneğin, "FF C0 00 11 08 01 DE 02 D0", 01DE 478 bir yüksekliğini temsil eder ve 02D0 720 bir genişliğe temsil eder.

Ben içeren bir GET isteği göndermek istediğiniz bir RANGE header mümkün (uzak sunucu ARALIK isteği onur olmayabilir ama yine de denemeye değer) gerçek veri aktarımını sınırlamak için. Muhtemelen yuvalarını (doğrudan) veya isteklerini yapmak için curl kullanımı olsun çok fark etmez. Ama ... Eğer kriterler olmadan asla bilemezsiniz. Kıvrılma için http://docs.php.net/function.curl-setopt de "CURLOPT_RANGE" seçeneğine bir göz atın

It probably doesn't fit your profile ("several an hour, on a server with only slim CPU power available.") but you might want to try handling multiple urls at a time, i.e. having multiple active connections and only handle those that won't block on a read operation. If the limiting factor is mostly/only cpu power ...forget this part. sockets: Take a look at stream_select curl: see curl_multi_exec()

Kıvırmak modül mevcut değilse de Aralık başlık içeren bir istek göndermek için stream_context_create() ile birlikte http url kapsayıcı kullanabilir.

Zaten bunu aldık bir kere veri ile ne anladım galiba.

Ben aşağıdaki rutin JPG, GIF, PNG ve sadece görüntü yükseklikleri almak, ya da 404 veya diğer görüntü türü üzerinde === FALSE surette iade düşünüyorum. File_get_contents () rota () Dosyayı indirmek getimagesize yok gibi aslında, hatta ilave bayt kısıtlama ile dosya indirmek için görünür, çünkü rutin da az sunucu kaynağı ile yapar. Bu oranla performans isabet görebilirsiniz.

Bu rutin işleri yolu dosyadan sadece 300 bayt indirir olmasıdır. Ne yazık ki JPEG, GIF ya da PNG aksine bir dosya oldukça uzaklarda yüksekliği değerini iter ve böylece ben uzaklarda bayt dosyayı okumak zorunda kaldım. Sonra, bu bayt ile, bize bu hangi dosya türü bildirmek için bu başlığa JFIF, PNG, GIF ya da tarar. Biz var, biz o başlığı ayrıştırmak için her benzersiz rutinleri kullanın. JPEG ilk H * ile unpack () kullanın ve sonra ffc2 veya ffc0 ve süreç için tarama gerektiğini unutmayın. GIF, ancak, ilk h * (orada büyük bir fark) () ile açmak gerekir.

Bu fonksiyon, deneme yanılma ile bana göre oluşturulan ve yanlış olabilir. Ben birkaç görüntü üzerinde koştu ve iyi çalışması için görünür. Bunu bir hata bulursanız, bana bildirerek düşünün.

Her neyse, bu sistem bana bir görüntü yüksekliğini belirler ve görüntüyü atar ve çok uzun boylu, başka bulsun olacaktır. Ben bulmak rastgele olursa olsun görüntü, ben HTML IMG etiketinin genişliğini ayarlamak ve otomatik yüksekliği boyutlandırır - ama görüntü belli bir yüksekliğe altında sadece iyi görünüyor. Yanı sıra, benim için başka bir sunucu tarafından döndürülen görüntü artık yok ya da cross-site bağlanmasını yasaklayan bir görüntü için değil, görmek için bir 404 denetimi yapar. Ve ben manuel olarak sabit bir genişliğe görüntüleri kuruyorum beri, ben görüntü genişliği okumak için umurumda değil. Bu adaptasyon fonksiyonu ve genellikle bunu yapmak istesin görüntü genişlikleri bulmak için sadece birkaç küçük bayt ileri bakabilirsiniz.

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;
}

Yerel görüntüleri depolamak. Bu çok basit ve garantili çözüm.