使用PHP读取远程文件

来源:http://www.software8.co/wzjs/PHPshili/527.html

从php读取一个远程文件你至少有四个选项:
 
1. 使用fopen()
2. 使用 file_get_contents()
3. CURL 
4,让你自己的函数使用php的socket函数。
 
首先我要警告你关于一些。你可以只使用 fopen()和 file_get_contents()当启用fopen包装器。这个参数中指定的php。ini文件并不能改变在运行时使用 ini设置(),知道你是否可以使用这两个或不可以使用下面的代码检查包装器设置的价值。fopen
if (ini_get('allow_url_fopen') == '1') {
   // 使用fopen()或file_get_contents()
} else {
   // 使用curl或定制函数
}
1。使用fopen()
 
如果你使用 fopen()阅读一个远程文件的过程很简单,从本地文件读取。唯一的区别是,您将指定URL而不是文件名。看看下面的例子:
 
/ /确保远程文件成功打开在做任何其他事情之前

 

if ($fp = fopen('http://www.google.com/', 'r')) {
   $content = '';
   // 继续阅读,直到没有什么离开
   while ($line = fread($fp, 1024)) {
      $content .= $line;
   }

   // 做一些与这里的内容
   // ...
} else {
   // 出错当试图打开指定的url
}

现在,上面的代码使用 fread()函数在while循环读取1024字节的数据在一个循环。这段代码还可以这样写:
 
/ /确保远程文件成功打开在做任何其他事情之前

if ($fp = fopen('http://www.google.com/', 'r')) {
   $content = '';
   // 继续阅读,直到没有什么离开
   while ($line = fgets($fp, 1024)) {
      $content .= $line;
   }

   // 做一些与这里的内容
   // ...
} else {
   // 出错当试图打开指定的url
}

 
相反的 fread()我们使用 fgets()它读取一行数据到1024字节。第一个代码更可取比第二虽然。想象一下如果远程文件的大小是50 kb和包含300行。使用第一个代码将导致循环执行了50次,但使用第二个循环将是执行三百次。
 
如果你考虑成本要调用一个函数加上所需的时间让300个请求的比例仅5然后显然第一个是赢家。
 
2。使用file_get_contents()
 
这是我最喜欢的阅读方式远程文件,因为它是非常简单的。只是调用这个函数,并指定一个url作为参数。但一定要记得检查返回值首先来决定它是否返回一个错误处理结果之前
$content = file_get_contents('http://www.google.com/');
if ($content !== false) {
   // 做些什么内容
} else {
   // 一个错误发生
}
 
3。curl
 

不同于上述两种方法使用CURL不能说为straigthforward。虽然这个库是非常有用的,可能不同的协议(而不仅仅是HTTP)进行连接和通信,它需要更多的精力来学习。另一个问题是,并非所有的Web主机有这个库中的PHP安装。因此,我们一定要检查库的安装,然后再尝试使用它。

这是一个基本的例子获取远程文件

/ /确保旋度是安装
if (function_exists('curl_init')) {
/ /初始化一个新的curl资源
 $ch = curl_init();
 
/ /设置url获取
 curl_setopt($ch, CURLOPT_URL, 'http://www.google.com');
 
/ /别给我头的内容
   curl_setopt($ch, CURLOPT_HEADER, 0);
/ /返回值,而不是打印响应浏览器
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
/ /使用一个用户代理模仿一个浏览器
   curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0');
 $content = curl_exec($ch);
/ /记得总是关闭会话和免费的所有资源
   curl_close($ch);
} else {
/ / curl库没有安装,所以我们更好地利用其他东西
}
 
在某些情况下使用CURL是速度比使用 file_get_contents()或 fopen()更快。这是因为CURL默认处理压缩协议(例如gzip)。许多网站,大的、小的、使用gzip压缩压缩他们的网页为了节省带宽。这个网站,例如,也使用gzip压缩,减少带宽使用到一半。所以,如果您是那种等不及的CURL将适合你。
 
4。定制函数
 
在最坏的情况下,您的服务器将禁用FOPEN包装,并没有安装CURL库。在这种情况下,你只需要做出你自己的方式。
 
我们的函数应当命名 getRemoteFile()这只需要一个参数,远程文件的url。对这个函数的骨架如下所示
function getRemoteFile($url)
{
/ / 1。把主机名和url路径
 
/ / 2。连接到远程服务器
 
/ / 3。发送必要的标题获取文件
 
/ / 4。检索响应来自远程服务器
 
/ / 5。strip the headers
 
/ / 6。返回文件的内容
 
提取的主机名和url路径从给定的url,我们将使用 parse_url()函数。当给定url这个函数会输出以下:
  • scheme
  • host
  • port
  • user
  • pass
  • path
  • query
  • fragment
 
例如,如果url http://www.php-mysql-tutorial.com/somepage.php然后 parse_url()将返回:
 
Array
(
    [scheme] => http
    [host] => www.php-mysql-tutorial.com
    [path] => /somepage.php
)
 
如果url http://myusername:mypassword@www.php-mysql-tutorial.com/somepage.php?q=whatsthis #ouch然后 parse_url()将返回这个:
 
Array
(
    [scheme] => http
    [host] => www.php-mysql-tutorial.com
    [user] => myusername
    [pass] => mypassword
    [path] => /somepage.php
    [query] => q=whatsthis
    [fragment] => ouch
)
 
为我们的新功能,我们只关心host, port, path and query.
 
可以建立一个连接到一个远程服务器我们使用 fsockopen()。这个函数只需要5个参数、hostname, port number,,a reference for error number, a reference for the error message and timeout
function getRemoteFile($url)
{
   // 把主机名和url路径
   $parsedUrl = parse_url($url);
   $host = $parsedUrl['host'];
   if (isset($parsedUrl['path'])) {
      $path = $parsedUrl['path'];
   } else {
      // url指向主机像http://www.mysite.com
      $path = '/';
   }

   if (isset($parsedUrl['query'])) {
      $path .= '?' . $parsedUrl['query'];
   }

   if (isset($parsedUrl['port'])) {
      $port = $parsedUrl['port'];
   } else {
      // 大多数网站使用端口80
      $port = '80';
   }

   $timeout = 10;
   $response = '';

   // 连接到远程服务器
   $fp = @fsockopen($host, '80', $errno, $errstr, $timeout );

   if( !$fp ) {
      echo "Cannot retrieve $url";
   } else {
      // 发送必要的标题获取文件
      fputs($fp, "GET $path HTTP/1.0\r\n" .
                 "Host: $host\r\n" .
                 "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3\r\n" .
                 "Accept: */*\r\n" .
                 "Accept-Language: en-us,en;q=0.5\r\n" .
                 "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" .
                 "Keep-Alive: 300\r\n" .
                 "Connection: keep-alive\r\n" .
                 "Referer: http://$host\r\n\r\n");

      // 检索响应来自远程服务器
      while ( $line = fread( $fp, 4096 ) ) {
         $response .= $line;
      }

      fclose( $fp );

      // strip the headers
      $pos      = strpos($response, "\r\n\r\n");
      $response = substr($response, $pos + 4);
   }

   // 返回文件的内容
   return $response;
}

上面的代码发送9行标题但只有前两个是强制性的。因此,即使你只发送这些
fputs($ fp”,获得$ path HTTP / 1.0 \ r \ n”。
“主持人:$主机\ r \ n \ r \ n”);
 
这个函数会正常工作。不总是虽然。因为该文件存储在一个远程服务器它真的到该服务器回复你的请求。有些人编写代码页阻止任何请求没有适当的引用页头。有些人会只接受一个特定的用户代理。其他需要cookie设置在头。
posted @ 2013-04-02 10:55  hasayaki  阅读(800)  评论(0编辑  收藏  举报