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

如果支持打开远程内容的选项的话,实际上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;
  }
}
?>

(0)

相关推荐

  • php自动提交表单的方法(基于fsockopen与curl)

    本文实例讲述了php基于fsockopen与curl实现自动提交表单的方法.分享给大家供大家参考,具体如下: fsockopen和curl都可以做php自动提交表单 1. fsockopen方法: php代码: <?php /*----------------------------------------------------------- *功能:使用PHP socke 向指定页面提交数据 *作者:果冻 说明:post($url, $data) * * $url = 'http://www

  • php使用fsockopen函数发送post,get请求获取网页内容的方法

    本文实例讲述了php使用fsockopen函数发送post,get请求获取网页内容的方法.分享给大家供大家参考. 具体实现代码如下: 复制代码 代码如下: $post =1; $url = parse_url($url); $host ='http://www.jb51.net'; $path ='/'; $query ='?action=phpfensi.com'; $port =80;   if($post) {   $out = "post $path http/1.0 ";  

  • php利用fsockopen GET/POST提交表单及上传文件

    php利用fsockopen GET/POST提交表单及上传文件,具体内容如下 1.GET get.php <?php $host = 'demo.fdipzone.com'; $port = 80; $errno = ''; $errstr = ''; $timeout = 30; $url = '/socket/getapi.php'; $param = array( 'name' => 'fdipzone', 'gender' => 'man' ); $url = $url.'?'

  • php fsockopen解决办法 php实现多线程

    回答:当有人想要实现并发功能时,他们通常会想到用fork或者spawn threads,但是当他们发现php不支持多线程的时候,大概会转换思路去用一些不够好的语言,比如perl.其实的是大多数情况下,你大可不必使用fork或者线程,并且你会得到比用fork或thread更好的性能.假设你要建立一个服务来检查正在运行的n台服务器,以确定他们还在正常运转.你可能会写下面这样的代码: 复制代码 代码如下: <?php $hosts = array("host1.sample.com",

  • php fsockopen伪造post与get方法的详解

    fsockopen 伪造 post和get方法哦,如果你正在找 伪造 post和get方法的php处理代码这款不错哦. 复制代码 代码如下: <?php//fsocket模拟post提交$purl = "http://localhost/netphp/test2.php?uu=rrrrrrrrrrrr";print_r(parse_url($url));sock_post($purl,"uu=55555555555555555");//fsocket模拟get

  • 利用PHP fsockopen 模拟POST/GET传送数据的方法

    使用php可以模拟 post 和 get 传送数据到别的网页或站点 $arr=array( 'user'=>'test', 'password'=>'' ); sock_get($post_url,$arr); sock_post($post_url,$arr); //fsocket模拟get提交 function sock_get($url,$query=array()){ $query_str = http_build_query($query); $<span id="_

  • php中fsockopen用法实例

    本文实例讲述了php中fsockopen用法.分享给大家供大家参考. 具体实现方法如下: 复制代码 代码如下: $fp=fsockopen("127.0.0.1",80);     //打开数据流 if(!$fp)           //如果打开出错 {   echo "unable to openn";       //输出内容 } else            //如果成功打开 {   fwrite($fp,"get / http/1.0rnrn&

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

    如果支持打开远程内容的选项的话,实际上php用fopen或file_get_contents都能获得一个网页的内容,但是默认的函数有个不足的地方就是无法获取HTTP头,这在一些特殊的应用中很不方便,如,有一个链接: http://www.abc.com/showvd.asp?id=18 假如它返回的是一个图片,用默认函数就很难识别,但如果通过HTTP应答头来判断就简单多了,此外如果对方通过 Refer 来防盗链的话,也是无法获取的,用HTTP类就能完美解决这些问题,而且速度也相差无几. 使用方法

  • c# 编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用法及配置文件,这对于有些小工具.小程序.小网站来说,有点"杀鸡焉俺用牛刀"的感觉,而且如果对这些日志框架不了解,可能输出来的日志性能或效果未毕是与自己所想的,鉴于这几个原因,我自己重复造轮子,编写了一个轻量级的异步写日志的实用工具类(LogAsyncWriter),这个类还是比较简单的,实

  • 详解基于vue-cli3快速发布一个fullpage组件

    前言 想必大家都看过fullpage.js--这是一款非常好用的翻页插件. 现在vue非常流行,大家想不想发布一个组件给别人使用呢? 这里我们基于vue-cli3快速搭建一个简单的fullpage组件给别人使用,当然你也可以做你感兴趣的组件发布给别人用~ GITHUB 链接 开始 准备 $ npm i -g @vue/cli #全局vue-cli3 通过查看vue-cli3官网了解,创建一个新的普通项目. 思考 一开始要想别人如何调用我们写的组件,通过挂载vue实例方法(this.$alert)

  • 基于vue如何发布一个npm包的方法步骤

    前言:工作的时候总是使用别人的npm包,然而我有时心底会好奇自己如何发布一个npm包呢,什么时候自己的包能够被很多人喜欢并使用呢...今天我终于迈出了第一步. 前提:会使用 npm,有 vue 基础,了解一点 webpack Are you ready? Go! 一.编写自己的npm包 1. 新建一个空文件夹 2. 进入文件夹,终端(cmd)运行 npm init 完成后会在目录下生成一个 package.json 文件 我们可以根据自己的需要补充文件内容 这是我的: { "name"

  • 发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser

    发布一个高效的JavaScript分析.压缩工具 JavaScript Analyser 先发一段脚本压缩示例,展示一下JSA语法压缩和优化功能. 复制代码 代码如下: try {         //xxxx();     } catch (e) {         yyyy();         function f1() {         }     } finally {         zzzz();     } function f2(var1) {         var var

  • 从零开始在NPM上发布一个Vue组件的方法步骤

    TL;DR 本文细致讲解了在NPM上发布一个Vue组件的全过程,包括创建项目.编写组件.打包和发布四个环节. 创建项目 这里我们直接利用@vue/cli来生成项目.如果没有安装@vue/cli的话,可以使用以下方法进行安装: # 如果喜欢npm npm i -g @vue/cli # 如果喜欢yarn yarn global add @vue/cli 此外,如果安装了npx(高版本的nodejs发行版会自带这一工具)的话,还可以很方便地通过npx vue这一方式实现免安装使用. 接下来就可以创建

  • 专为新手写的结合smarty的类第1/3页

    专为新手写的结合smarty的类,诚挚邀请大家多提宝贵意见 这个是为新手(也为自己)写的结合smarty一起使用的类,是未完成的,现在放出来的目的不是马上让新手使用,所以也没有把注解写的非常详细 希望各位高手多多提意见,我尽量完善它.     首先声明,我写这个的目的也是为了锻炼自己,尽管我知道现在已经有很多类似的类了,但是我还是决定来写一个, 所以请大家在浏览的时候口下留情. 还有文件我也已经打包上传了,放在下面,请大家多多下载,多多提意见.有什么问题直接Q我 目前该类包括以下功能(使用范例,

  • PHP写的资源下载防盗链类分享

    这几天在写一个PHP防盗链外部资源下载处理函数,昨天晚上刚完成编写,中间遇到了些问题,这里就不详述了:以下是自写的简单的PHP防盗链处理类(重新整理编写成类文件,以便后期改进): 复制代码 代码如下: <?php/** * * 防盗链外部资源下载处理类 *  * @link   http://jb51.net *  */class BurglarDow{ /**     * 初始许可下载状态     * @var    allow     * @access private     */ pri

  • 一个可查询所有表的“通用”查询分页类

    一个可查询所有表的"通用"查询分页类 最近突发奇想,希望写出一个可以针对所有表的查询分页类.因为在实际的开发中,恐怕查询并将结果集分页显示是用得最多的代码,而表的结构是多样的,我想尽可能地提高代码的重用率和维护性. 以下是我写的,请各位加以指点,测试,看能否进行更好的改进和更多的支持. 目前还只支持单一的表,不支持联合查询.但未来可以会考虑如何支持. 代码: <?php /******************************************************

  • 聊聊@Autowired注解注入,写接口名字还是实现类的名字

    目录 用@Autowired注解注入,写接口名字还是实现类的名字 来自某程序员一个问答问题 Spring中Autowired注入接口的几个问题 1.Spring怎么知道注入哪个实现? 2.需要@Qualifier和@Resource注解吗? 3.为什么@Autowired使用在interface上而不是实现类上? 用@Autowired注解注入,写接口名字还是实现类的名字 来自某程序员一个问答问题 1. 有一点没明白,为什么注解@repository注解的是接口UserDAO的实现类UserDA

随机推荐