通过php实现支持断点续传的http proxy

该博客介绍了利用PHP实现支持断点续传的HTTP Proxy。借助PHP语言的特性,达成HTTP代理的断点续传功能,在信息技术领域有一定应用价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过php实现支持断点续传的http proxy

练手的程序,
目前仅支持http协议,
暂不支持header重定向的处理.
有兴趣的可以看看^_^

<?php
/***************************************/
/**/
/*Php Http Proxy*/
/*version: 0.0.2*/
/*last modify: 2005.1.12*/
/*author: q3boy<q3boy@sina.com>*/
/**/
/***************************************/
set_time_limit(180);

define('PP_ERROR_CODE',1);
define('PP_ERROR_MESSAGE',2);
define('PP_ERROR_ALL',3);
define('PP_RETURN_STRING',1);
define('PP_RETURN_ARRAY',2);
define('PP_RETURN_ALL',3);

class
CPhpProxy {

var
$_strUrl;
var
$_arrArgv;
var
$_strRef;
var
$_arrUrl;
var
$_resSocket;
var
$_intError;
var
$_strError;
var
$_arrDefaultArrayUrl;
var
$_arrDefaultPort;

function
CPhpProxy($strUrl = null, $arrArgv = array()) {
$this->init();
is_null($strUrl)?'':$this->setUrl($strUrl);
is_null($arrArgv['refer'])?'':$this->setRef($arrArgv['refer']);
$this->proxy($strUrl,$arrArgv);
}
function
setError($intError,$mixArgv=null) {
$this->_intError = $intError;
if(
$intError==1001) {
$this->_strError = "调用 $mixArgv 方法时参数传递出错, 枚举值不存在";
}elseif(
$intError==1) {
$this->_strError = "url 错误, url 格式不正确./n".$mixArgvs;
}elseif(
$intError == 2) {
$this->_strError = "url 错误, 目前尚未支持此协议./n".$mixArgvs;
}elseif(
$intError == 3) {
$this->_strError = "无法打开 ".$this->_arrUrl['host'].':'.$this->_arrUrl['port']."/n".$mixArgv[0].': '.$mixArgv[1];
}

Return
false;
}

function
getError($enumReturnType=PP_ERROR_CODE) {
if(
$enumReturnType==PP_ERROR_ALL) {
Return array(
str_pad($this->_intError,5,'0',STR_PAD_LEFT),$this->_strError);
}elseif(
$enumReturnType==PP_ERROR_MESSAGE) {
Return
$this->_strError;
}elseif(
$enumReturnType==PP_ERROR_CODE) {
Return
$this->_intError;
}else {
Return
false;
}
}

function
init() {
$this->_strUrl = null;
$this->_arrArgv = array();
$this->_strRef = null;
$this->_arrUrl = array();
$this->_resSocket = null;
$this->_intError = 0;
$this->_strError = 'there is no error';
//arrurl 默认值
$this->_arrDefaultArrayUrl = array('protocol'=>'http','file'=>'index.htm');
//默认端口
$this->_arrDefaultPort =array('http'=>'80');
Return
true;
}
function
setUrl($strUrl) {
$strUrl = trim($strUrl);
//正则
$reg = "/^(([/w]+):////)?([^:|//|@]*:)?([^:|//|@]*@)?([/w|/-|/.]+)(:/d+)?(//[^/?|#]*)?(/?[^#]*)?(#.*)?$/is";
if(!
preg_match($reg,$strUrl,$arrUrl)) {
Return
$this->setError(1,$strUrl);
}else {
//拆解匹配数组
list($tmp, $tmp, $arr['protocol'], $arr['user'], $arr['pass'], $arr['host'], $arr['port'], $arr['path'], $arr['query'], $arr['anchor']) = $arrUrl;
//默认协议
if(!$arr['protocol']) {
$arrUrl[1] = $this->_arrDefaultArrayUrl['protocol'].'://';
}
//设 filename
$arr['file'] = basename($arr['path']);
//默认值
foreach($this->_arrDefaultArrayUrl as $key=>$val) {
if(
$arr[$key] == '') {
$arr[$key] = $val;
}
}
//默认端口
if(is_null($this->_arrDefaultPort[$arr['protocol']])) {
Return
$this->setError(2,$arr['protocol']);
}elseif(!
$arr['port']) {
$arr['port'] = $this->_arrDefaultPort[$arr['protocol']];
}

//设 uri
$arr['uri']= ($arr['path']?$arr['path']:'/') . ($arr['query']?'?'.$arr['query']:'') . ($arr['anchor']?'#'.$arr['anchor']:'');
//设 url
unset($arrUrl[0]);
unset(
$arrUrl[2]);
$this->_strUrl = implode('',$arrUrl);
//设 arrurl
$this->_arrUrl = $arr;
Return
true;
}
}
function
getUrl($enumReturnType = PP_RETURN_ARRAY) {
if(
$enumReturnType==PP_RETURN_STRING) {
Return
$this->_strUrl;
}elseif(
$enumReturnType==PP_RETURN_ARRAY) {
Return
$this->_arrUrl;
}if(
$enumReturnType==PP_RETURN_ALL) {
Return array(
$this->_strUrl,$this->_arrUrl);
}else {
Return
$this->setError(1001);
}

}
function
setRefer($strRef) {
$this->_strRef = trim($strRef);
Return
true;
}
function
getRefer() {
Return
$this->_strRef;
}

function
getProxyUrl() {
global
$_SERVER;
list(
$strProcotol) = explode('/',strtolower(trim($_SERVER['SERVER_PROTOCOL'])));
$str = $strProcotol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].
'?u='.urlencode($this->getUrl(PP_RETURN_STRING)).
(
$this->getRefer()?('&r='.urlencode($this->getRefer())):'');
Return
$str;
}
function
openSocket() {
$arr = $this->getUrl();
$this->_resSocket = @fsockopen($arr['host'],$arr['port'],$intError, $strError, 30);
if(!
$this->_resSocket) {
$this->_resSocket = null;
Return
$this->setError(3,array($intError, $strError));
}else {
Return
true;
}
}
function
getRequest() {
Return
$this->{ 'get'.ucfirst($this->_arrUrl['protocol']).'Request' }();
}
function
sendRequest() {
Return
fwrite($this->_resSocket,$this->getRequest());
}
function
flushResponse() {
Return
$this->{ 'flush'.ucfirst($this->_arrUrl['protocol']).'Response' }();
}
function
getHttpRequest() {
$arr = $this->getUrl();
$arrRequest = getallheaders();
$arrRequest['Host'] = $arr['host'];
$strRequest= "GET ".$arr['uri']." HTTP/1.1/r/n";
foreach(
$arrRequest as $key=>$val) {
$strRequest .="$key: $val/r/n";
}
$strRequest .="/r/n";
Return
$strRequest;
}
function
flushHttpResponse() {
$bolHeader=true;
while (!
feof($this->_resSocket)) {
$str = fgets($this->_resSocket, 4096);
if(
$bolHeader) {
@
header($str);
}else {
echo(
$str);
}
if(
$bolHeader && $str=="/r/n") {
$bolHeader=false;
@
header("Content-type: application/gzip");
@
header('Content-Disposition: attachment; filename="'.$this->_arrUrl['file'].'"');
}
}
Return
true;
}
function
close() {
fclose($this->_resSocket);
$this->_resSocket = null;
Return
true;
}
function
proxy($strUrl = null,$arrArgv = array()) {
if(!
is_null($this->getUrl(PP_RETURN_STRING)) && $this->openSocket() && $this->sendRequest() && $this->flushResponse()) {
echo(
123);
$this->close();
}else {
Return
false;
}
}
}
if(
sizeof($_GET)) {
$strGetArrayName = '_GET';
}elseif(
sizeof($HTTP_GET_VARS)) {
$strGetArrayName = 'HTTP_GET_VARS';
}else {
die(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>PhpProxy</title>
<style type="text/css">
<!--body,td { font-family: verdana; font-size: 12px; }th,input { font-family: verdana; }-->
</style>
</head>
<body>
<form name="form1" method="get" action="'
.$_SERVER['PHP_SELF'].'">
<table width="500" border="1" align="center" cellpadding="5" cellspacing="1">
<tr>
<th colspan="2">PhpProxy</th>
</tr>
<tr>
<td width="39" nowrap>URL:</td>
<td width="432"><input name="u" type="text" id="u" size="60"></td>
</tr>
<tr>
<td nowrap>REFERER:</td>
<td><input name="r" type="text" id="r" size="60"></td>
</tr>
<tr>
<td colspan="2" align="center"><input name="act" value="make" type="hidden">
<input type="submit" value="Get Proxy Url">
<input type="reset"value="Reset"></td>
</tr>
</table>
</form>
</body>
</html>'
);
}
$strUrl = trim(${ $strGetArrayName }['u']);
if(
$strUrl=='') {
die(
'请输入 url 地址.');
}
//get referer
$strRefTmp = trim(${ $strGetArrayName }['r']);
//初始化 proxy 类
$objProxy = new CPhpProxy();
//设置 url 和 refer
$objProxy->setUrl($strUrl);
$objProxy->setRefer($strRef);
//错误输出
if($objProxy->getError()) {
die(
$objProxy->getError(PP_ERROR_MESSAGE));
}

//echo url for download
if(${ $strGetArrayName }['act']=='make') {
die(
"<center><h4><a href='".$objProxy->getProxyUrl()."'>点击此处通过 PhpProxy 下载文件</a></h2></center>");
}
//取文件
$objProxy->proxy();
//错误处理
if($objProxy->getError()) {
die(
$objProxy->getError(PP_ERROR_MESSAGE));
}
?>

<?php
/***************************************/
/**/
/*Php Http Proxy*/
/*version: 0.0.2*/
/*last modify: 2005.1.12*/
/*author: q3boy<q3boy@sina.com>*/
/**/
/***************************************/
set_time_limit(180);

define('PP_ERROR_CODE',1);
define('PP_ERROR_MESSAGE',2);
define('PP_ERROR_ALL',3);
define('PP_RETURN_STRING',1);
define('PP_RETURN_ARRAY',2);
define('PP_RETURN_ALL',3);

class
CPhpProxy {

var
$_strUrl;
var
$_arrArgv;
var
$_strRef;
var
$_arrUrl;
var
$_resSocket;
var
$_intError;
var
$_strError;
var
$_arrDefaultArrayUrl;
var
$_arrDefaultPort;

function
CPhpProxy($strUrl = null, $arrArgv = array()) {
$this->init();
is_null($strUrl)?'':$this->setUrl($strUrl);
is_null($arrArgv['refer'])?'':$this->setRef($arrArgv['refer']);
$this->proxy($strUrl,$arrArgv);
}
function
setError($intError,$mixArgv=null) {
$this->_intError = $intError;
if(
$intError==1001) {
$this->_strError = "调用 $mixArgv 方法时参数传递出错, 枚举值不存在";
}elseif(
$intError==1) {
$this->_strError = "url 错误, url 格式不正确./n".$mixArgvs;
}elseif(
$intError == 2) {
$this->_strError = "url 错误, 目前尚未支持此协议./n".$mixArgvs;
}elseif(
$intError == 3) {
$this->_strError = "无法打开 ".$this->_arrUrl['host'].':'.$this->_arrUrl['port']."/n".$mixArgv[0].': '.$mixArgv[1];
}

Return
false;
}

function
getError($enumReturnType=PP_ERROR_CODE) {
if(
$enumReturnType==PP_ERROR_ALL) {
Return array(
str_pad($this->_intError,5,'0',STR_PAD_LEFT),$this->_strError);
}elseif(
$enumReturnType==PP_ERROR_MESSAGE) {
Return
$this->_strError;
}elseif(
$enumReturnType==PP_ERROR_CODE) {
Return
$this->_intError;
}else {
Return
false;
}
}

function
init() {
$this->_strUrl = null;
$this->_arrArgv = array();
$this->_strRef = null;
$this->_arrUrl = array();
$this->_resSocket = null;
$this->_intError = 0;
$this->_strError = 'there is no error';
//arrurl 默认值
$this->_arrDefaultArrayUrl = array('protocol'=>'http','file'=>'index.htm');
//默认端口
$this->_arrDefaultPort =array('http'=>'80');
Return
true;
}
function
setUrl($strUrl) {
$strUrl = trim($strUrl);
//正则
$reg = "/^(([/w]+):////)?([^:|//|@]*:)?([^:|//|@]*@)?([/w|/-|/.]+)(:/d+)?(//[^/?|#]*)?(/?[^#]*)?(#.*)?$/is";
if(!
preg_match($reg,$strUrl,$arrUrl)) {
Return
$this->setError(1,$strUrl);
}else {
//拆解匹配数组
list($tmp, $tmp, $arr['protocol'], $arr['user'], $arr['pass'], $arr['host'], $arr['port'], $arr['path'], $arr['query'], $arr['anchor']) = $arrUrl;
//默认协议
if(!$arr['protocol']) {
$arrUrl[1] = $this->_arrDefaultArrayUrl['protocol'].'://';
}
//设 filename
$arr['file'] = basename($arr['path']);
//默认值
foreach($this->_arrDefaultArrayUrl as $key=>$val) {
if(
$arr[$key] == '') {
$arr[$key] = $val;
}
}
//默认端口
if(is_null($this->_arrDefaultPort[$arr['protocol']])) {
Return
$this->setError(2,$arr['protocol']);
}elseif(!
$arr['port']) {
$arr['port'] = $this->_arrDefaultPort[$arr['protocol']];
}

//设 uri
$arr['uri']= ($arr['path']?$arr['path']:'/') . ($arr['query']?'?'.$arr['query']:'') . ($arr['anchor']?'#'.$arr['anchor']:'');
//设 url
unset($arrUrl[0]);
unset(
$arrUrl[2]);
$this->_strUrl = implode('',$arrUrl);
//设 arrurl
$this->_arrUrl = $arr;
Return
true;
}
}
function
getUrl($enumReturnType = PP_RETURN_ARRAY) {
if(
$enumReturnType==PP_RETURN_STRING) {
Return
$this->_strUrl;
}elseif(
$enumReturnType==PP_RETURN_ARRAY) {
Return
$this->_arrUrl;
}if(
$enumReturnType==PP_RETURN_ALL) {
Return array(
$this->_strUrl,$this->_arrUrl);
}else {
Return
$this->setError(1001);
}

}
function
setRefer($strRef) {
$this->_strRef = trim($strRef);
Return
true;
}
function
getRefer() {
Return
$this->_strRef;
}

function
getProxyUrl() {
global
$_SERVER;
list(
$strProcotol) = explode('/',strtolower(trim($_SERVER['SERVER_PROTOCOL'])));
$str = $strProcotol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].
'?u='.urlencode($this->getUrl(PP_RETURN_STRING)).
(
$this->getRefer()?('&r='.urlencode($this->getRefer())):'');
Return
$str;
}
function
openSocket() {
$arr = $this->getUrl();
$this->_resSocket = @fsockopen($arr['host'],$arr['port'],$intError, $strError, 30);
if(!
$this->_resSocket) {
$this->_resSocket = null;
Return
$this->setError(3,array($intError, $strError));
}else {
Return
true;
}
}
function
getRequest() {
Return
$this->{ 'get'.ucfirst($this->_arrUrl['protocol']).'Request' }();
}
function
sendRequest() {
Return
fwrite($this->_resSocket,$this->getRequest());
}
function
flushResponse() {
Return
$this->{ 'flush'.ucfirst($this->_arrUrl['protocol']).'Response' }();
}
function
getHttpRequest() {
$arr = $this->getUrl();
$arrRequest = getallheaders();
$arrRequest['Host'] = $arr['host'];
$strRequest= "GET ".$arr['uri']." HTTP/1.1/r/n";
foreach(
$arrRequest as $key=>$val) {
$strRequest .="$key: $val/r/n";
}
$strRequest .="/r/n";
Return
$strRequest;
}
function
flushHttpResponse() {
$bolHeader=true;
while (!
feof($this->_resSocket)) {
$str = fgets($this->_resSocket, 4096);
if(
$bolHeader) {
@
header($str);
}else {
echo(
$str);
}
if(
$bolHeader && $str=="/r/n") {
$bolHeader=false;
@
header("Content-type: application/gzip");
@
header('Content-Disposition: attachment; filename="'.$this->_arrUrl['file'].'"');
}
}
Return
true;
}
function
close() {
fclose($this->_resSocket);
$this->_resSocket = null;
Return
true;
}
function
proxy($strUrl = null,$arrArgv = array()) {
if(!
is_null($this->getUrl(PP_RETURN_STRING)) && $this->openSocket() && $this->sendRequest() && $this->flushResponse()) {
echo(
123);
$this->close();
}else {
Return
false;
}
}
}
if(
sizeof($_GET)) {
$strGetArrayName = '_GET';
}elseif(
sizeof($HTTP_GET_VARS)) {
$strGetArrayName = 'HTTP_GET_VARS';
}else {
die(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>PhpProxy</title>
<style type="text/css">
<!--body,td { font-family: verdana; font-size: 12px; }th,input { font-family: verdana; }-->
</style>
</head>
<body>
<form name="form1" method="get" action="'
.$_SERVER['PHP_SELF'].'">
<table width="500" border="1" align="center" cellpadding="5" cellspacing="1">
<tr>
<th colspan="2">PhpProxy</th>
</tr>
<tr>
<td width="39" nowrap>URL:</td>
<td width="432"><input name="u" type="text" id="u" size="60"></td>
</tr>
<tr>
<td nowrap>REFERER:</td>
<td><input name="r" type="text" id="r" size="60"></td>
</tr>
<tr>
<td colspan="2" align="center"><input name="act" value="make" type="hidden">
<input type="submit" value="Get Proxy Url">
<input type="reset"value="Reset"></td>
</tr>
</table>
</form>
</body>
</html>'
);
}
$strUrl = trim(${ $strGetArrayName }['u']);
if(
$strUrl=='') {
die(
'请输入 url 地址.');
}
//get referer
$strRefTmp = trim(${ $strGetArrayName }['r']);
//初始化 proxy 类
$objProxy = new CPhpProxy();
//设置 url 和 refer
$objProxy->setUrl($strUrl);
$objProxy->setRefer($strRef);
//错误输出
if($objProxy->getError()) {
die(
$objProxy->getError(PP_ERROR_MESSAGE));
}

//echo url for download
if(${ $strGetArrayName }['act']=='make') {
die(
"<center><h4><a href='".$objProxy->getProxyUrl()."'>点击此处通过 PhpProxy 下载文件</a></h2></center>");
}
//取文件
$objProxy->proxy();
//错误处理
if($objProxy->getError()) {
die(
$objProxy->getError(PP_ERROR_MESSAGE));
}
?>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值