此文章来源于后羿之弓,转载请注明出处

通常我们会用php去检测远程文件是否存或者是判断远程文件类型,以及通过文件大小来判断远程文件是否有效(比如一首正常的流行歌曲的mp3文件不会少于300k吧)。
方法众多,本人觉得通过socket抓出HTTP报头来判断无疑是性价比最优的。下面就是通过修改HttpClient得到了一个getFileHeader的类(含有示例及结果)

  1. <?php 
  2. error_reporting(0);
  3.  
  4. header('content-type:text/html; charset=utf-8');
  5. $mp3url = 'http://learning.sohu.com/zt/freshenglish/sep17/songs.mp3';
  6.  
  7. $request = new getFileHeader($mp3url);
  8. $request->doRequest();
  9. var_dump($request->getHeaders());
  10.  
  11. class getFileHeader{
  12.     var $host;//主机
  13.     var $file;//远端文件
  14.     var $port;//端口
  15.     var $path;
  16.     var $username;
  17.     var $password;
  18.  
  19.     var $timeout = 8;
  20.     var $debug = false;
  21.  
  22.     var $use_gzip = true;
  23.     var $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*';
  24.     var $accept_encoding = 'gzip, deflate';
  25.     var $accept_language = 'zh-cn';
  26.     var $user_agent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; (R1 1.3); .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)';
  27.     var $cookies = array('__utma'=>'130375891.1873577237.1204525960.1205473824.1205476776.10','__utmz'=>'130375891.1205397510.8.2.utmccn=(referral)|utmcsr=music.tyfo.com|utmcct=/music_dht.html|utmcmd=referral','__utmb=130375891','ASP.NET_SessionId'=>'bzr0w2455juwyly53k0gh4fr','__utmc'=>'130375891');
  28.     var $referer;
  29.  
  30.     var $headers;
  31.     var $errormsg;
  32.     var $status;
  33.     function __construct($file){
  34.         $fileinfo = parse_url($file);
  35.         $this->file = $file;
  36.         $this->path = @$fileinfo['path'].$fileinfo['query'];
  37.         $this->host = $fileinfo['host'];
  38.         $this->username = @$fileinfo['user'];
  39.         $this->username = @$fileinfo['pass'];
  40.         $this->port = @$fileinfo['port'] ? intval($fileinfo['port']) : 80;
  41.     }
  42.  
  43.     function buildRequest() {
  44.         $headers = array();
  45.         $headers[] = "GET {$this->path} HTTP/1.0"; // Using 1.1 leads to all manner of problems, such as "chunked" encoding
  46.         $headers[] = "Host: {$this->host}";
  47.         $headers[] = "User-Agent: {$this->user_agent}";
  48.         $headers[] = "Accept: {$this->accept}";
  49.         if ($this->use_gzip) {
  50.             $headers[] = "Accept-encoding: {$this->accept_encoding}";
  51.         }
  52.         $headers[] = "Accept-language: {$this->accept_language}";
  53.         if ($this->referer) {
  54.             $headers[] = "Referer: {$this->referer}";
  55.         }
  56.         // Cookies
  57.         if ($this->cookies) {
  58.             $cookie = 'Cookie: ';
  59.             foreach ($this->cookies as $key => $value) {
  60.                 $cookie .= "$key=$value; ";
  61.             }
  62.             $headers[] = $cookie;
  63.         }
  64.         // Basic authentication
  65.         if ($this->username && $this->password) {
  66.             $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password);
  67.         }
  68.  
  69.         $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata;
  70.         return $request;
  71.     }
  72.  
  73.     function doRequest() {
  74.         if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) {
  75.             switch($errno) {
  76.                 case -3:
  77.                     $this->errormsg = 'Socket creation failed (-3)';
  78.                 case -4:
  79.                     $this->errormsg = 'DNS lookup failure (-4)';
  80.                 case -5:
  81.                     $this->errormsg = 'Connection refused or timed out (-5)';
  82.                 default:
  83.                     $this->errormsg = 'Connection failed ('.$errno.')';
  84.                     $this->errormsg .= ' '.$errstr;
  85.                     $this->debug($this->errormsg);
  86.             }
  87.             return false;
  88.         }
  89.         socket_set_timeout($fp, $this->timeout);
  90.         $request = $this->buildRequest();
  91.         $this->debug('Request', $request);
  92.         fwrite($fp, $request);
  93.         // Reset all the variables that should not persist between requests
  94.         $this->headers = array();
  95.  
  96.         $this->errormsg = '';
  97.         // Set a couple of flags
  98.         $inHeaders = true;
  99.         $atStart = true;
  100.         // Now start reading back the response
  101.         while (!feof($fp)) {
  102.             $line = fgets($fp, 4096);
  103.             if ($atStart) {
  104.                 // Deal with first line of returned data
  105.                 $atStart = false;
  106.                 if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) {
  107.                     $this->errormsg = "Status code line invalid: ".htmlentities($line);
  108.                     $this->debug($this->errormsg);
  109.                     return false;
  110.                 }
  111.                 $http_version = $m[1]; // not used
  112.                 $this->status = $m[2];
  113.                 $status_string = $m[3]; // not used
  114.                 $this->debug(trim($line));
  115.                 continue;
  116.             }
  117.             if ($inHeaders) {
  118.                 if (trim($line) == '') {
  119.                     $inHeaders = false;
  120.                     $this->debug('Received Headers', $this->headers);
  121.                     if ($this->headers_only) {
  122.                         break; // Skip the rest of the input
  123.                     }
  124.                     continue;
  125.                 }
  126.                 if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) {
  127.                     // Skip to the next header
  128.                     continue;
  129.                 }
  130.                 $key = strtolower(trim($m[1]));
  131.                 $val = trim($m[2]);
  132.                 // Deal with the possibility of multiple headers of same name
  133.                 if (isset($this->headers[$key])) {
  134.                     if (is_array($this->headers[$key])) {
  135.                         $this->headers[$key][] = $val;
  136.                     } else {
  137.                         $this->headers[$key] = array($this->headers[$key], $val);
  138.                     }
  139.                 } else {
  140.                     $this->headers[$key] = $val;
  141.                 }
  142.                 continue;
  143.             }
  144.             break;
  145.         }
  146.         fclose($fp);
  147.     }
  148.  
  149.     function getHeaders() {
  150.         return $this->headers;
  151.     }
  152.  
  153.     function debug($msg, $object = false) {
  154.         if ($this->debug) {
  155.             print '<div style="border: 1px solid red; padding: 0.5em; margin: 0.5em;"><strong>HttpClient Debug:</strong> '.$msg;
  156.             if ($object) {
  157.                 ob_start();
  158.                 print_r($object);
  159.                 $content = htmlentities(ob_get_contents());
  160.                 ob_end_clean();
  161.                 print '<pre>'.$content.'</pre>';
  162.             }
  163.             print '</div>';
  164.         }
  165.     }
  166. }
  167. ?>

上述代码执行的结果是

  1. array(14) {
  2.   ["date"]=>
  3.   string(29) "Wed, 01 Jul 2009 13:07:17 GMT"
  4.   ["server"]=>
  5.   string(39) "Apache/1.3.37 (Unix) mod_gzip/1.3.26.1a"
  6.   ["vary"]=>
  7.   string(15) "Accept-Encoding"
  8.   ["cache-control"]=>
  9.   string(11) "max-age=120"
  10.   ["expires"]=>
  11.   string(29) "Wed, 01 Jul 2009 13:09:17 GMT"
  12.   ["last-modified"]=>
  13.   string(29) "Tue, 23 Sep 2003 10:31:20 GMT"
  14.   ["etag"]=>
  15.   string(24) ""6d414a-252dd5-3f7020f8""
  16.   ["accept-ranges"]=>
  17.   string(5) "bytes"
  18.   ["content-length"]=>
  19.   string(7) "2436565"
  20.   ["content-type"]=>
  21.   string(10) "audio/mpeg"
  22.   ["age"]=>
  23.   string(2) "52"
  24.   ["x-cache"]=>
  25.   string(44) "HIT from 31145605.40779458.40031417.sohu.com"
  26.   ["via"]=>
  27.   string(50) "1.0 31145605.40779458.40031417.sohu.com:80 (squid)"
  28.   ["connection"]=>
  29.   string(5) "close"
  30. }