发布一个用PHP fsockopen写的HTTP下载的类


Posted in PHP onFebruary 22, 2007

如果支持打开远程内容的选项的话,实际上php用fopen或file_get_contents都能获得一个网页的内容,但是默认的函数有个不足的地方就是无法获取HTTP头,这在一些特殊的应用中很不方便,如,有一个链接:

http://www.abc.com/showvd.asp?id=18 

假如它返回的是一个图片,用默认函数就很难识别,但如果通过HTTP应答头来判断就简单多了,此外如果对方通过 Refer 来防盗链的话,也是无法获取的,用HTTP类就能完美解决这些问题,而且速度也相差无几。

使用方法:

$hd = new DedeHttpDown();
$hd->OpenUrl("http://www.dedecms.com");
echo $hd->GetHtml();
//如果保存为文件则用 $hd->SaveBin("dede.html");
$hd->Close();

获得http请求头用
$hd->GetHead("key")
设置请求头
$hd->SetHead(key,value); (必须在调用 OpenUrl 之前设定)

代码如下:

<?
/* ---------------------------------------------------------------------
//织梦Http下载类V1.0
//出自:织梦之旅 http://www.dedecms.com
//作者: IT柏拉图
//时间: 2005-11-13 12:39
//声明: 首发在落伍者网站,转载请保留版权信息
--------------------------------------------------------------------- */
class DedeHttpDown
{
        var $m_url = "";
        var $m_urlpath = "";
        var $m_scheme = "http";
        var $m_host = "";
        var $m_port = "80";
        var $m_user = "";
        var $m_pass = "";
        var $m_path = "/";
        var $m_query = "";
        var $m_fp = "";
        var $m_error = "";
        var $m_httphead = "" ;
        var $m_html = "";
        var $m_puthead = "";
        var $BaseUrlPath = "";
        var $HomeUrl = "";
        var $JumpCount = 0;//防止多重重定向陷入死循环
        //
        //初始化系统
        //
        function PrivateInit($url)
        {
                        if($url=="") return ;
                        $urls = "";
                        $urls = @parse_url($url);
                        $this->m_url = $url;
            if(is_array($urls))
            {
                          $this->m_host = $urls["host"];
                          if(!empty($urls["scheme"])) $this->m_scheme = $urls["scheme"];

                          if(!empty($urls["user"])){
                                        $this->m_user = $urls["user"];
                          }

                          if(!empty($urls["pass"])){
                                        $this->m_pass = $urls["pass"];
                          }

                          if(!empty($urls["port"])){
                                        $this->m_port = $urls["port"];
                          }

                          if(!empty($urls["path"])) $this->m_path = $urls["path"];
                          $this->m_urlpath = $this->m_path;

                          if(!empty($urls["query"])){
                                        $this->m_query = $urls["query"];
                                        $this->m_urlpath .= "?".$this->m_query;
                          }
                          $this->HomeUrl = $urls["host"];
                          $this->BaseUrlPath = $this->HomeUrl.$urls["path"];
                          $this->BaseUrlPath = ereg_replace("/([^/]*)\.(.*)$","/",$this->BaseUrlPath);
                          $this->BaseUrlPath = ereg_replace("/$","",$this->BaseUrlPath);
                 }
        }
        //
        //打开指定网址
        //
        function OpenUrl($url)
        {
                //重设各参数
                $this->m_url = "";
                $this->m_urlpath = "";
                $this->m_scheme = "http";
                $this->m_host = "";
                $this->m_port = "80";
                $this->m_user = "";
                $this->m_pass = "";
                $this->m_path = "/";
                $this->m_query = "";
                $this->m_error = "";
                $this->JumpCount = 0;
                $this->m_httphead = Array() ;
                //$this->m_puthead = "";
                $this->m_html = "";
                $this->Close();
                //初始化系统
                $this->PrivateInit($url);
                $this->PrivateStartSession();
        }
        //
        //打开303重定向网址
        //
        function JumpOpenUrl($url)
        {
                //重设各参数
                $this->m_url = "";
                $this->m_urlpath = "";
                $this->m_scheme = "http";
                $this->m_host = "";
                $this->m_port = "80";
                $this->m_user = "";
                $this->m_pass = "";
                $this->m_path = "/";
                $this->m_query = "";
                $this->m_error = "";
                $this->JumpCount++;
                $this->m_httphead = Array() ;
                $this->m_html = "";
                $this->Close();
                //初始化系统
                $this->PrivateInit($url);
                $this->PrivateStartSession();
        }
        //
        //获得某操作错误的原因
        //
        function printError()
        {
                echo "错误信息:".$this->m_error;
                echo "具体返回头:<br>";
                foreach($this->m_httphead as $k=>$v)
                { echo "$k => $v <br>\r\n"; }
        }
        //
        //判别用Get方法发送的头的应答结果是否正确
        //
        function IsGetOK()
        {
                if( ereg("^2",$this->GetHead("http-state")) )
                {        return true; }
                else
                {
                        $this->m_error .= $this->GetHead("http-state")." - ".$this->GetHead("http-describe")."<br>";
                        return false;
                }
        }
        //
        //看看返回的网页是否是text类型
        //
        function IsText()
        {
                if(ereg("^2",$this->GetHead("http-state"))
                        && eregi("^text",$this->GetHead("content-type")))
                {        return true; }
                else
                {
                        $this->m_error .= "内容为非文本类型或网址重定向<br>";
                        return false;
                }
        }
        //
        //判断返回的网页是否是特定的类型
        //
        function IsContentType($ctype)
        {
                if(ereg("^2",$this->GetHead("http-state"))
                        && $this->GetHead("content-type")==strtolower($ctype))
                {        return true; }
                else
                {
                        $this->m_error .= "类型不对 ".$this->GetHead("content-type")."<br>";
                        return false;
                }
        }
        //
        //用Http协议下载文件
        //
        function SaveToBin($savefilename)
        {
                if(!$this->IsGetOK()) return false;
                if(@feof($this->m_fp)) { $this->m_error = "连接已经关闭!"; return false; }
                $fp = fopen($savefilename,"w");
                while(!feof($this->m_fp)){
                        fwrite($fp,fread($this->m_fp,1024));
                }
                fclose($this->m_fp);

                fclose($fp);
                return true;
        }
        //
        //保存网页内容为Text文件
        //
        function SaveToText($savefilename)
        {
                if($this->IsText()) $this->SaveBinFile($savefilename);
                else return "";
        }
        //
        //用Http协议获得一个网页的内容
        //
        function GetHtml()
        {
                if(!$this->IsText()) return "";
                if($this->m_html!="") return $this->m_html;
                if(!$this->m_fp||@feof($this->m_fp)) return "";
                while(!feof($this->m_fp)){
                        $this->m_html .= fgets($this->m_fp,256);
                }
                @fclose($this->m_fp);
                return $this->m_html;
        }
        //
        //开始HTTP会话
        //
        function PrivateStartSession()
        {

                if(!$this->PrivateOpenHost()){
                        $this->m_error .= "打开远程主机出错!";
                        return false;
                }

                if($this->GetHead("http-edition")=="HTTP/1.1") $httpv = "HTTP/1.1";
                else $httpv = "HTTP/1.0";

                //发送固定的起始请求头GET、Host信息
                fputs($this->m_fp,"GET ".$this->m_urlpath." $httpv\r\n");
                $this->m_puthead["Host"] = $this->m_host;

                //发送用户自定义的请求头
                if(!isset($this->m_puthead["Accept"])) { $this->m_puthead["Accept"] = "*/*"; }
                if(!isset($this->m_puthead["User-Agent"])) { $this->m_puthead["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)"; }
                if(!isset($this->m_puthead["Refer"])) { $this->m_puthead["Refer"] = "http://".$this->m_puthead["Host"]; }
                foreach($this->m_puthead as $k=>$v){
                        $k = trim($k);
                        $v = trim($v);
                        if($k!=""&&$v!=""){
                                fputs($this->m_fp,"$k: $v\r\n");
                        }
                }

                //发送固定的结束请求头
                //HTTP1.1协议必须指定文档结束后关闭链接,否则读取文档时无法使用feof判断结束
                if($httpv=="HTTP/1.1") fputs($this->m_fp,"Connection: Close\r\n\r\n");
                else fputs($this->m_fp,"\r\n");

                //获取应答头状态信息
                $httpstas = explode(" ",fgets($this->m_fp,256));
                $this->m_httphead["http-edition"] = trim($httpstas[0]);
                $this->m_httphead["http-state"] = trim($httpstas[1]);
                $this->m_httphead["http-describe"] = "";
                for($i=2;$i<count($httpstas);$i++){
                        $this->m_httphead["http-describe"] .= " ".trim($httpstas[$i]);
                }
                //获取详细应答头
                while(!feof($this->m_fp)){
                        $line = trim(fgets($this->m_fp,256));
                        if($line == "") break;
                        $hkey = "";
                        $hvalue = "";
                        $v = 0;
                        for($i=0;$i<strlen($line);$i++){
                                if($v==1) $hvalue .= $line[$i];
                                if($line[$i]==":") $v = 1;
                                if($v==0) $hkey .= $line[$i];
                        }
                        $hkey = trim($hkey);
                        if($hkey!="") $this->m_httphead[strtolower($hkey)] = trim($hvalue);
                }
                //判断是否是3xx开头的应答
                if(ereg("^3",$this->m_httphead["http-state"]))
                {
                        if($this->JumpCount > 3) return;
                        if(isset($this->m_httphead["location"])){
                                $newurl = $this->m_httphead["location"];
                                if(eregi("^http",$newurl)){
                                        $this->JumpOpenUrl($newurl);
                                }
                                else{
                                        $newurl = $this->FillUrl($newurl);
                                        $this->JumpOpenUrl($newurl);
                                }
                        }
                        else
                        {        $this->m_error = "无法识别的转移应答!"; }
                }//
        }
        //
        //获得一个Http头的值
        //
        function GetHead($headname)
        {
                $headname = strtolower($headname);
                if(isset($this->m_httphead[$headname]))
                        return $this->m_httphead[$headname];
                else
                        return "";
        }
        //
        //设置Http头的值
        //
        function SetHead($skey,$svalue)
        {
                $this->m_puthead[$skey] = $svalue;
        }
        //
        //打开连接
        //
        function PrivateOpenHost()
        {
                if($this->m_host=="") return false;
                $this->m_fp = @fsockopen($this->m_host, $this->m_port, &$errno, &$errstr,10);
                if(!$this->m_fp){
                        $this->m_error = $errstr;
                        return false;
                }
                else{
                        return true;
                }
        }
        //
        //关闭连接
        //
        function Close(){
                @fclose($this->m_fp);
        }
        //
        //补全相对网址
        //
        function FillUrl($surl)
  {
    $i = 0;
    $dstr = "";
    $pstr = "";
    $okurl = "";
    $pathStep = 0;
    $surl = trim($surl);
    if($surl=="") return "";
    $pos = strpos($surl,"#");
    if($pos>0) $surl = substr($surl,0,$pos);
    if($surl[0]=="/"){
            $okurl = "http://".$this->HomeUrl."/".$surl;
    }
    else if($surl[0]==".")
    {
      if(strlen($surl)<=2) return "";
      else if($surl[0]=="/")
      {
              $okurl = "http://".$this->BaseUrlPath."/".substr($surl,2,strlen($surl)-2);
            }
      else{
        $urls = explode("/",$surl);
        foreach($urls as $u){
          if($u=="..") $pathStep++;
          else if($i<count($urls)-1) $dstr .= $urls[$i]."/";
          else $dstr .= $urls[$i];
          $i++;
        }
        $urls = explode("/",$this->BaseUrlPath);
        if(count($urls) <= $pathStep)
                return "";
        else{
          $pstr = "http://";
          for($i=0;$i<count($urls)-$pathStep;$i++)
          { $pstr .= $urls[$i]."/"; }
          $okurl = $pstr.$dstr;
        }
      }
    }
    else
    {
      if(strlen($surl)<7)
        $okurl = "http://".$this->BaseUrlPath."/".$surl;
      else if(strtolower(substr($surl,0,7))=="http://")
        $okurl = $surl;
      else
        $okurl = "http://".$this->BaseUrlPath."/".$surl;
    }
    $okurl = eregi_replace("^(http://)","",$okurl);
    $okurl = eregi_replace("/{1,}","/",$okurl);
    return "http://".$okurl;
  }
}
?>

PHP 相关文章推荐
php的list()的一步操作给一组变量进行赋值的使用
May 18 PHP
php学习笔记 数组遍历实现代码
Jun 09 PHP
php设计模式 Composite (组合模式)
Jun 26 PHP
深入PHP变量存储的详解
Jun 13 PHP
PHP Class&amp;Object -- 解析PHP实现二叉树
Jun 25 PHP
php防止伪造数据从地址栏URL提交的方法
Aug 24 PHP
smarty中英文多编码字符截取乱码问题解决方法
Oct 28 PHP
8个PHP程序员常用的功能汇总
Dec 18 PHP
php中JSON的使用方法
Apr 30 PHP
php动态变量定义及使用
Jun 10 PHP
支付宝服务窗API接口开发php版本
Jul 20 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
Mar 12 PHP
隐藏X-Space个人空间下方版权方法隐藏X-Space个人空间标题隐藏X-Space个人空间管理版权方法
Feb 22 #PHP
excellent!――ASCII Art(由目标图象生成ascii)
Feb 20 #PHP
珊瑚虫IP库浅析
Feb 15 #PHP
PHP中HTTP方式下的Gzip压缩传输方法举偶
Feb 15 #PHP
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
Feb 15 #PHP
php调用mysql存储过程
Feb 14 #PHP
mysql中存储过程、函数的一些问题
Feb 14 #PHP
You might like
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
php多次include后导致全局变量global失效的解决方法
2015/02/28 PHP
PHP异常类及异常处理操作实例详解
2018/12/19 PHP
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
2010/03/02 Javascript
JavaScript异步编程Promise模式的6个特性
2014/04/03 Javascript
jquery datatable后台封装数据示例代码
2014/08/07 Javascript
JavaScript的内存释放问题详解
2015/01/21 Javascript
JavaScript实现可拖拽的拖动层Div实例
2015/08/05 Javascript
详解JavaScript函数对象
2015/11/15 Javascript
Js删除数组中某一项或几项的几种方法(推荐)
2016/07/27 Javascript
NodeJS远程代码执行
2016/08/28 NodeJs
webpack实现热加载自动刷新的方法
2017/07/30 Javascript
AngularJS通过ng-Img-Crop实现头像截取的示例
2017/08/17 Javascript
es6数据变更同步到视图层的方法
2019/03/04 Javascript
JavaScript中的一些实用小技巧总结
2019/04/07 Javascript
Vue data的数据响应式到底是如何实现的
2020/02/11 Javascript
利用Psyco提升Python运行速度
2014/12/24 Python
初步介绍Python中的pydoc模块和distutils模块
2015/04/13 Python
python中实现指定时间调用函数示例代码
2017/09/08 Python
python实现批量修改文件名代码
2017/09/10 Python
Python通用循环的构造方法实例分析
2018/12/19 Python
对Python中DataFrame选择某列值为XX的行实例详解
2019/01/29 Python
Python使用Turtle库绘制一棵西兰花
2019/11/23 Python
python else语句在循环中的运用详解
2020/07/06 Python
Python logging日志库空间不足问题解决
2020/09/14 Python
CSS3实现曲线阴影和翘边阴影
2016/05/03 HTML / CSS
CSS3 filter(滤镜)实现网页灰色或者黑色模式的示例代码
2021/02/24 HTML / CSS
HTML5中判断横屏竖屏的方法(移动端)
2016/08/04 HTML / CSS
体育纪念品、亲笔签名的体育收藏品:Steiner Sports
2020/07/31 全球购物
建筑工程技术应届生自荐信
2013/09/27 职场文书
创业计划书中包含的9个方面
2013/12/26 职场文书
超市国庆节促销方案
2014/02/20 职场文书
美容院经理岗位职责
2014/04/03 职场文书
学校社会实践活动总结
2014/07/03 职场文书
欢迎词范文
2015/01/27 职场文书
2015年党员个人工作总结
2015/05/13 职场文书