ホームページ  >  記事  >  バックエンド開発  >  DedeHttpDown PHP リモート ダウンロード Web ページ クラス、2013 年 1 月 17 日に変更された拡張バージョン_PHP チュートリアル

DedeHttpDown PHP リモート ダウンロード Web ページ クラス、2013 年 1 月 17 日に変更された拡張バージョン_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-14 10:08:12987ブラウズ

1) サーバーリソースを節約するためにリモートホスト判定を追加します。リモート ホストが存在しない場合は fsockopen を使用しないでください。クラッシュが発生してサーバーの CPU が占有されてしまいます。

(2) 401への対応の判定とサポートを追加しました。
(3) json で返されるテキストのサポートを追加します。
(4) ログ生成。DEBUG_LEVEL が設定され、TRUE の場合、リモート ダウンロードごとにログが生成されます。
(5) サーバー リソースを節約するために、バイトの制限された dataLimit を取得します。
(6) 更新日: 2013-1-17
より良い提案があれば、いつでも私に連絡してください。 admin@zbphp.com
[php]
/**
* Dreamweaver HTTP ダウンロード クラス
*
* @version $Id: dedehttpdown.class.php 1 2010 年 7 月 6 日 11:42 Ztianya $
* @パッケージDedeCMS.Libraries
* @copyright 著作権 (c) 2007 - 2010、DesDev, Inc.
* @著者を変更 admin@zbphp.com
* @license http://help.dedecms.com/usersguide/license.html
* @link http://www.dedecms.com
*/
@set_time_limit(0);
クラス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 $dataLimit = 0;
var $m_puthead = '';
var $BaseUrlPath = '';
var $HomeUrl = '';
var $reTry = 0;
var $JumpCount = 0;
/**
* 初期化システム
*
* @アクセス公開
* @param string $url ダウンロードするアドレス
* @戻り文字列
*/
関数PrivateInit($url)
{
if($url=='') {
}
$url = '';
$url = @parse_url($url);
$this->m_url = $url;
if(is_array($urls))
$this->m_host = $urls["host"];
if(!emptyempty($urls["scheme"]))
$this->m_scheme = $urls["scheme"];
}
if(!emptyempty($urls["user"]))
$this->m_user = $urls["user"];
}
if(!emptyempty($urls["pass"]))
$this->m_pass = $urls["pass"];
}
if(!emptyempty($urls["port"]))
{
$this->m_port = $urls["port"];  
}
if(!emptyempty($urls["path"]))
{
$this->m_path = $urls["path"];  
}
$this->m_urlpath = $this->m_path;  
if(!emptyempty($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 = preg_replace("//([^/]*).(.*)$/","/",$this->BaseUrlPath);  
$this->BaseUrlPath = preg_replace("//$/","",$this->BaseUrlPath);  
}
}
/**
* 各パラメータをリセットします
*
* @アクセス公開
* @return void
*/
関数 ResetAny()
{
$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 = "";  
}
/**
*指定されたURLを開きます
*
* @アクセス公開
* @param string $url アドレス
* @param string $requestType リクエストタイプ
* @戻り文字列
*/
function OpenUrl($url,$requestType="GET")
{
$this->ResetAny();  
$this->JumpCount = 0;  
$this->m_httphead = Array() ;  
$this->m_html = '';  
$this->dataLimit = 0;  
$this->reTry = 0;  
$this->Close();  
//初化系统
$this->PrivateInit($url);  
$this->PrivateStartSession($requestType);  
}
/**
* 转到303重定向网址
*
* @access public
* @param string $url 地址
* @return string
*/
関数 JumpOpenUrl($url)
{
$this->ResetAny();  
$this->JumpCount++;  
$this->m_httphead = Array() ;  
$this->m_html = "";  
$this->Close();  
//初化系统
$this->PrivateInit($url);  
$this->PrivateStartSession('GET');  
}
/**
* 操作エラーの理由を取得します
*
* @アクセス公開
* @return void
*/
関数 printError()
{
echo "错误情報:".$this->m_error;  
echo "
特定の返头:
";  
foreach($this->m_httphead as $k=>$v){ echo "$k => $v
rn"; }
}
/**
* Getメソッドで送信したヘッダーの応答結果が正しいか判定します
*
* @アクセス公開
* @return bool
*/
関数 IsGetOK()
{
if( preg_match("/^2/",$this->GetHead("http-state")) )
{
TRUE を返します。  
}
その他
{
$this->m_error .= $this->GetHead("http-state")." - ".$this->GetHead("http-describe")."
";  
FALSE を返します。  
}
}
/**
* 返された Web ページがテキスト タイプかどうかを確認します
*
* @アクセス公開
* @return bool
*/
関数 IsText()
{
if( preg_match("/^(2|401)/",$this->GetHead("http-state")) && preg_match("/text|xml|json/i",$this->GetHead) ("コンテンツタイプ")) )
{
TRUE を返します。  
} else {
$this->m_error .= "内容は非文本类型または网址重定方向
";  
FALSE を返します。  
}
}
/**
* 返された Web ページが特定のタイプであるかどうかを判断します
*
* @アクセス公開
* @param string $ctype コンテンツ タイプ
* @戻り文字列
*/
関数 IsContentType($ctype)
{
if(preg_match("/^2/",$this->GetHead("http-state"))
&& $this->GetHead("content-type")==strto lower($ctype))
{ TRUE を返します。 }
その他
{
$this->m_error .= "类型不对 ".$this->GetHead("content-type")."
";  
FALSE を返します。  
}
}
/**
* HTTPプロトコルを使用してファイルをダウンロードします
*
* @アクセス公開
* @param string $savefilename 保存ファイル名
* @戻り文字列
*/
関数 SaveToBin($savefilename)
{
if(!$this->IsGetOK())
{
FALSE を返します。  
}
if(@feof($this->m_fp))
{
$this->m_error = "连接已经关闭!"; FALSEを返します。  
}
$fp = fopen($savefilename,"w");  
while(!feof($this->m_fp))
{
fwrite($fp, fread($this->m_fp, 1024));  
}
fclose($this->m_fp);  
fclose($fp);  
TRUE を返します。  
}
/**
* Web コンテンツをテキスト ファイルとして保存します
*
* @アクセス公開
* @param string $savefilename 保存ファイル名
* @戻り文字列
*/
関数 SaveToText($savefilename)
{
if($this->IsText())
{
$this->SaveBinFile($savefilename);  
}
その他
{
"" を返します。  
}
}
/**
* Web ページのコンテンツを取得するには、HTTP プロトコルを使用します
*
* @アクセス公開
* @戻り文字列
*/
関数 GetHtml()
{
$tm1 = microtime(true);  
if(!$this->IsText())
{
戻ります '';  
}
if($this->m_html!='')
{
return $this->m_html;  
}
if(!$this->m_fp||@feof($this->m_fp))
{
戻ります '';  
}
while(!feof($this->m_fp))
{
$this->m_html .= fgets($this->m_fp,256);  
if($this->dataLimit > 0 && strlen($this->m_html) > $this->dataLimit) Break;  
}
@fclose($this->m_fp);  
$tm2 = microtime(true);  
$log = "ntm2-tm1 = ".($tm2-$tm1);  
$log.= "n".$this->m_html;  
$this->log_write('GetHtml',$log);  
return $this->m_html;  
}
/**
* HTTPセッションを開始します
*
* @アクセス公開
* @param string $requestType リクエストタイプ
* @戻り文字列
*/
関数 PrivateStartSession($requestType="GET")
{
if(!$this->PrivateOpenHost())
{
$this->m_error .= "打开远程主机出错!";  
FALSE を返します。  
}
$this->reTry++;  
if($this->GetHead("http-edition")=="HTTP/1.1")
{
$httpv = "HTTP/1.1";  
}
その他
{
$httpv = "HTTP/1.0";  
}
$ps =explode('?',$this->m_urlpath);  
$headString = '';  
//固定の開始请要求头GET、ホスト情報を送信します
if($requestType=="GET")
{
$headString .= "GET ".$this->m_urlpath." $httpvrn";  
}
その他
{
$headString .= "POST ".$ps[0]." $httpvrn";  
}
if($this->m_user || $this->m_pass)
{
$headString .= "認可: 基本 ".base64_encode($this->m_user.":".$this->m_pass)."rn";  
}
$this->m_puthead["ホスト"] = $this->m_host;  
//送信用户自定的请求头
if(!isset($this->m_puthead["User-Agent"]))
{
$this->m_puthead["User-Agent"] = "Mozilla/4.0 (互換性; MSIE 6.0; Windows NT 5.2)";  
}
if(!isset($this->m_puthead["Refer"]))
{
$this->m_puthead["参照"] = "http://".$this->m_puthead["ホスト"];  
}
/* 2012-12-19 追加 */
$headString.="接続:キープアライブ";  
$headString.="Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3rn";  
$headString.="Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn";  
foreach($this->m_puthead as $k=>$v)
{
$k = トリム($k);  
$v = トリム($v);  
if($k!=""&&$v!="")
{
$headString .= "$k: $vrn";  
}
}
fputs($this->m_fp, $headString);  
if($requestType=="POST")
{
$postdata = "";  
if(count($ps)>1)
{
for($i=1;$i
{
$postdata .= $ps[$i];  
}
}
その他
{
$postdata = "OK";  
}
$plen = strlen($postdata);  
fputs($this->m_fp,"Content-Type: application/x-www-form-urlencodedrn");  
fputs($this->m_fp,"Content-Length: $plenrn");  
}
//送信固定的结束请求头
//HTTP1.1协议必须指定文档结束後关闭链接、否则读取文档時無法使用feof判断结束
if($httpv=="HTTP/1.1")
{
fputs($this->m_fp,"接続: Closernrn");  
}
その他
{
fputs($this->m_fp,"rn");  
}
if($requestType=="POST")
{
fputs($this->m_fp,$postdata);  
}
//获取应答头状態态情報
$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
{
$this->m_httphead["http-describe"] .= " ".trim($httpstas[$i]);  
}
//获取详细应答头
while(!feof($this->m_fp))
{
$line = trim(fgets($this->m_fp,256));  
if($line == "")
{
休憩。  
}
$hkey = "";  
$hvalue = "";  
$v = 0;  
for($i=0;$i
{
if($v==1)
{
$hvalue .= $line[$i];  
}
if($line[$i]==":")
{
$v = 1;  
}
if($v==0)
{
$hkey .= $line[$i];  
}
}
$hkey = トリム($hkey);  
if($hkey!="")
{
$this->m_httphead[strto lower($hkey)] = trim($hvalue);  
}
}
//如果连接被不正常关闭、重试
if(feof($this->m_fp))
{
if($this->reTry > 10)
{
FALSE を返します。  
}
$this->PrivateStartSession($requestType);  
}
// 判断は3xx开头の应答
if(preg_match("/^3/",$this->m_httphead["http-state"]))
{
if($this->JumpCount > 3)
{
戻る;  
}
if(isset($this->m_httphead["location"]))
{
$newurl = $this->m_httphead["location"];  
if(preg_match("/^http/i",$newurl))
{
$this->JumpOpenUrl($newurl);  
}
その他
{
$newurl = $this->FillUrl($newurl);  
$this->JumpOpenUrl($newurl);  
}
}
その他
{
$this->m_error = "無法识别的回答复!";  
}
}
}
/**
* HTTP ヘッダーの値を取得します
*
* @アクセス公開
* @param string $headname ヘッダーファイル名
* @戻り文字列
*/
関数 GetHead($headname)
{
$headname = strto lower($headname);  
return isset($this->m_httphead[$headname]) ? $this->m_httphead[$headname] : '';  
}
/**
* HTTPヘッダーの値を設定します
*
* @アクセス公開
* @param string $skey キー
* @param 文字列 $svalue 値
* @戻り文字列
*/
関数 SetHead($skey,$svalue)
{
$this->m_puthead[$skey] = $svalue;  
}
/**
* オープン接続
*
* @アクセス公開
* @return bool
*/
関数 PrivateOpenHost()
{
if($this->m_host=="")
{
FALSE を返します。  
}
if(function_exists('checkdnsrr') && !checkdnsrr($this->m_host,'A') && !checkdnsrr($this->m_host,'CNAME'))
{
$this->m_error = '远程主机'.$this->m_host.'不存在!checkdnsrr !';  
FALSE を返します。  
}
$errno = "";  
$errstr = "";  
$this->m_fp = @fsockopen($this->m_host, $this->m_port, $errno, $errstr,10);  
if(!$this->m_fp)
{
$this->m_error = $errstr;  
FALSE を返します。  
}
その他
{
TRUE を返します。  
}
}
/**
*密接なつながり
*
* @アクセス公開
* @return void
*/
関数 Close()
{
@fclose($this->m_fp);  
}
/**
* 完全な相対 URL
*
* @アクセス公開
* @param string $surl には不完全なアドレスが必要です
* @戻り文字列
*/
関数 FillUrl($surl)
{
$i = 0;  
$dstr = "";  
$pstr = "";  
$okurl = "";  
$pathStep = 0;  
$surl = トリム($surl);  
if($surl=="")
{
"" を返します。  
}
$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)<=1)
{
"" を返します。  
}
else if($surl[1]=="/")
{
$okurl = "http://".$this->BaseUrlPath."/".substr($surl,2,strlen($surl)-2);  
}
その他
{
$urls =explode("/",$surl);  
foreach($urls as $u)
{
if($u=="..")
{
$pathStep++;  
}
else if($i
{
$dstr .= $urls[$i]."/";  
}
その他
{
$dstr .= $urls[$i];  
}
$i++;  
}
$urls =explode("/",$this->BaseUrlPath);  
if(count($urls)
{
"" を返します。  
}
その他
{
$pstr = "http://";  
for($i=0;$i
{
$pstr .= $urls[$i]."/";  
}
$okurl = $pstr.$dstr;  
}
}
}
その他
{
if(strlen($surl)
{
$okurl = "http://".$this->BaseUrlPath."/".$surl;  
}
else if(strto lower(substr($surl,0,7))=="http://")
{
$okurl = $surl;  
}
その他
{
$okurl = "http://".$this->BaseUrlPath."/".$surl;  
}
}
$okurl = preg_replace("/^(http://)/i","",$okurl);  
$okurl = preg_replace("//{1,}/", "/", $okurl);  
"http://".$okurl を返します。  
}
function log_write($funcname,$message)
{
if(!(定義('DEBUG_LEVEL') && DEBUG_LEVEL == TRUE)) return ;  
$log = "n".date("Y-M-d H:i:s ").get_current_user()."[".getmypid()."]";  
$log.= "n".$this->m_url."n".str_repeat('------', 10)."n".$message;  
$path = $funcname.' '.date('Y m d H i s ').preg_replace('/([W]+|s+)/i', ' ', $this->m_url);  
if(strlen($path) > 250) $path = substr($path,0,250);  
$dir = DEDEDATA.'/httpdownlog';  
if(!is_dir($dir) && !mkdir($dir)) exit('ディレクトリを作成できません '.$dir);  
$path = $dir.'/'.$path;  
if(!file_exists($path)) touch($path);  
$fp = fopen($path,'a+');  
flock($fp, LOCK_EX);  
fputs($fp, "PATH:".$path."nREAL:".realpath($path)."nMSSG:".$log);  
fclose($fp);  
TRUE を返します。  
}
}//授業終了
使用方法:
[php]
$dhd = 新しい DeDeHttpDown();  
$dhd->OpenUrl($Rs['wurl']);  
$dhd->dataLimit = 5120;  
$dhd->m_puthead["参照"] = $Rs['wurl'];  
$filecnt = トリム($dhd->GetHtml());  
未解決の问题が存在します:
(1)ドメイン名に認証と CNAME が設定されている場合、IP アドレスが指定されているが、IP アドレスが存在しないか空である場合、プログラムは古いセッションを継続して取得します。
(2)PHP の fsockopen セクションのタイムアウト現象は根本的に機能しません。10 秒のタイムアウトが設定されていますが、根本的にはプログラムの実行がタイムアウトになります。
良い方法が確立されれば、私自身が随時接続することができます。admin@zbphp.com

www.bkjia.com本当http://www.bkjia.com/PHPjc/477811.html技術記事 1) サーバーリソースを節約するためにリモートホスト判定を追加します。リモートホストが存在しない場合にクラッシュを引き起こし、サーバーのCPUを占有してしまうfsockopenを回避する (2) 401への応答の判定とサポートを追加...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。