php下载远程文件类(支持断点续传)


Posted in PHP onNovember 14, 2008

简易使用方法: 

$object = new httpdownload(); 
$object->set_byfile($file)%N#H#%;//服务器文件名,包括路径 
$object->filename = $filename;//下载另存为的文件名 
$object->download();

3.源文件:

<? 
class httpdownload { 
var $data = null; 
var $data_len = 0; 
var $data_mod = 0; 
var $data_type = 0; 
var $data_section = 0; //section download 
var $sentSize=0; 
var $handler = array('auth' => null); 
var $use_resume = true; 
var $use_autoexit = false; 
var $use_auth = false; 
var $filename = null; 
var $mime = null; 
var $bufsize = 2048; 
var $seek_start = 0; 
var $seek_end = -1; 
var $totalsizeref = 0; 
var $bandwidth = 0; 
var $speed = 0; 
function initialize() { 
global $HTTP_SERVER_VARS; 
if ($this->use_auth) //use authentication 
{ 
if (!$this->_auth()) //no authentication 
{ 
header('WWW-Authenticate: Basic realm="Please enter your username and password"'); 
header('HTTP/1.0 401 Unauthorized'); 
header('status: 401 Unauthorized'); 
if ($this->use_autoexit) exit(); 
return false; 
} 
} 
if ($this->mime == null) $this->mime = "application/octet-stream"; //default mime 
if (isset($_SERVER['HTTP_RANGE']) || isset($HTTP_SERVER_VARS['HTTP_RANGE'])) 
{ 
if (isset($HTTP_SERVER_VARS['HTTP_RANGE'])) $seek_range = substr($HTTP_SERVER_VARS['HTTP_RANGE'] , strlen('bytes=')); 
else $seek_range = substr($_SERVER['HTTP_RANGE'] , strlen('bytes=')); 
$range = explode('-',$seek_range); 
if ($range[0] > 0) 
{ 
$this->seek_start = intval($range[0]); 
} 
if ($range[1] > 0) $this->seek_end = intval($range[1]); 
else $this->seek_end = -1; 
if (!$this->use_resume) 
{ 
$this->seek_start = 0; 
//header("HTTP/1.0 404 Bad Request"); 
//header("Status: 400 Bad Request"); 
//exit; 
//return false; 
} 
else 
{ 
$this->data_section = 1; 
} 
} 
else 
{ 
$this->seek_start = 0; 
$this->seek_end = -1; 
} 
$this->sentSize=0; 
return true; 
} 
function header($size,$seek_start=null,$seek_end=null) { 
header('Content-type: ' . $this->mime); 
header('Content-Disposition: attachment; filename="' . $this->filename . '"'); 
header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T' , $this->data_mod)); 
if ($this->data_section && $this->use_resume) 
{ 
header("HTTP/1.0 206 Partial Content"); 
header("Status: 206 Partial Content"); 
header('Accept-Ranges: bytes'); 
header("Content-Range: bytes $seek_start-$seek_end/$size"); 
header("Content-Length: " . ($seek_end - $seek_start + 1)); 
} 
else 
{ 
header("Content-Length: $size"); 
} 
} 
function download_ex($size) 
{ 
if (!$this->initialize()) return false; 
ignore_user_abort(true); 
//Use seek end here 
if ($this->seek_start > ($size - 1)) $this->seek_start = 0; 
if ($this->seek_end <= 0) $this->seek_end = $size - 1; 
$this->header($size,$seek,$this->seek_end); 
$this->data_mod = time(); 
return true; 
} 
function download() { 
if (!$this->initialize()) return false; 
try 
{ 
error_log("begin download\n", 3,"/usr/local/www/apache22/LOGS/apache22_php.err"); 
$seek = $this->seek_start; 
$speed = $this->speed; 
$bufsize = $this->bufsize; 
$packet = 1; 
//do some clean up 
@ob_end_clean(); 
$old_status = ignore_user_abort(true); 
@set_time_limit(0); 
$this->bandwidth = 0; 
$size = $this->data_len; 
if ($this->data_type == 0) //download from a file 
{ 
$size = filesize($this->data); 
if ($seek > ($size - 1)) $seek = 0; 
if ($this->filename == null) $this->filename = basename($this->data); 
$res = fopen($this->data,'rb'); 
if ($seek) fseek($res , $seek); 
if ($this->seek_end < $seek) $this->seek_end = $size - 1; 
$this->header($size,$seek,$this->seek_end); //always use the last seek 
$size = $this->seek_end - $seek + 1; 
while (!(connection_aborted() || connection_status() == 1) && $size > 0) 
{ 
if ($size < $bufsize) 
{ 
echo fread($res , $size); 
$this->bandwidth += $size; 
$this->sentSize+=$size; 
} 
else 
{ 
echo fread($res , $bufsize); 
$this->bandwidth += $bufsize; 
$this->sentSize+=$bufsize; 
} 
$size -= $bufsize; 
flush(); 
if ($speed > 0 && ($this->bandwidth > $speed*$packet*1024)) 
{ 
sleep(1); 
$packet++; 
} 
} 
fclose($res); 
} 
elseif ($this->data_type == 1) //download from a string 
{ 
if ($seek > ($size - 1)) $seek = 0; 
if ($this->seek_end < $seek) $this->seek_end = $this->data_len - 1; 
$this->data = substr($this->data , $seek , $this->seek_end - $seek + 1); 
if ($this->filename == null) $this->filename = time(); 
$size = strlen($this->data); 
$this->header($this->data_len,$seek,$this->seek_end); 
while (!connection_aborted() && $size > 0) { 
if ($size < $bufsize) 
{ 
$this->bandwidth += $size; 
$this->sentSize+=$size; 
} 
else 
{ 
$this->bandwidth += $bufsize; 
$this->sentSize+=$bufsize; 
} 
echo substr($this->data , 0 , $bufsize); 
$this->data = substr($this->data , $bufsize); 
$size -= $bufsize; 
flush(); 
if ($speed > 0 && ($this->bandwidth > $speed*$packet*1024)) 
{ 
sleep(1); 
$packet++; 
} 
} 
} else if ($this->data_type == 2) { 
//just send a redirect header 
header('location: ' . $this->data); 
} 
if($this->totalsizeref==$this->sentSize )error_log("end download\n", 3,"/usr/local/www/apache22/LOGS/apache22_php.err"); 
else error_log("download is canceled\n", 3,"/usr/local/www/apache22/LOGS/apache22_php.err"); 
if ($this->use_autoexit) exit(); 
//restore old status 
ignore_user_abort($old_status); 
set_time_limit(ini_get("max_execution_time")); 
} 
catch(Exception $e) 
{ 
error_log("cancel download\n".$e, 3,"/usr/local/www/apache22/LOGS/apache22_php.err"); 
} 
return true; 
} 
function set_byfile($dir) { 
if (is_readable($dir) && is_file($dir)) { 
$this->data_len = 0; 
$this->data = $dir; 
$this->data_type = 0; 
$this->data_mod = filemtime($dir); 
$this->totalsizeref = filesize($dir); 
return true; 
} else return false; 
} 
function set_bydata($data) { 
if ($data == '') return false; 
$this->data = $data; 
$this->data_len = strlen($data); 
$this->data_type = 1; 
$this->data_mod = time(); 
return true; 
} 
function set_byurl($data) { 
$this->data = $data; 
$this->data_len = 0; 
$this->data_type = 2; 
return true; 
} 
function set_lastmodtime($time) { 
$time = intval($time); 
if ($time <= 0) $time = time(); 
$this->data_mod = $time; 
} 
function _auth() { 
if (!isset($_SERVER['PHP_AUTH_USER'])) return false; 
if (isset($this->handler['auth']) && function_exists($this->handler['auth'])) 
{ 
return $this->handler['auth']('auth' , $_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); 
} 
else return true; //you must use a handler 
} 
} 
?>

PHP 相关文章推荐
打造计数器DIY三步曲(下)
Oct 09 PHP
PHP Pear 安装及使用
Mar 19 PHP
PHP去掉从word直接粘贴过来的没有用格式的函数
Oct 29 PHP
PHP中array_merge和array相加的区别分析
Jun 17 PHP
使用PHP导出Word文档的原理和实例
Oct 21 PHP
php过滤表单提交的html等危险代码
Nov 03 PHP
Codeigniter检测表单post数据的方法
Mar 21 PHP
php实现的xml操作类
Jan 15 PHP
CodeIgniter视图使用注意事项
Jan 20 PHP
Zend Framework缓存Cache用法简单实例
Mar 19 PHP
php文件上传类完整实例
May 14 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
May 06 PHP
PHP ajax 分页类代码
Nov 13 #PHP
使用Limit参数优化MySQL查询的方法
Nov 12 #PHP
mysql limit查询优化分析
Nov 12 #PHP
令PHP初学者头疼十四条问题大总结
Nov 12 #PHP
PHP程序61条面向对象分析设计的经验小结
Nov 12 #PHP
Php Cookie的一个使用注意点
Nov 08 #PHP
MySql 按时间段查询数据方法(实例说明)
Nov 02 #PHP
You might like
PHP启动windows应用程序、执行bat批处理、执行cmd命令的方法(exec、system函数详解)
2014/10/20 PHP
jQuery获取json后使用zy_tmpl生成下拉菜单
2015/03/27 PHP
windows7配置Nginx+php+mysql的详细教程
2016/09/04 PHP
图片img的src不变让浏览器重新加载实现方法
2013/03/29 Javascript
jquery通过a标签删除table中的一行的代码
2013/12/02 Javascript
jQuery EasyUI Dialog拖不下来如何解决
2015/09/28 Javascript
浏览器兼容性问题大汇总
2015/12/17 Javascript
js+html5实现canvas绘制椭圆形图案的方法
2016/05/21 Javascript
微信小程序实现图片自适应(支持多图)
2017/01/25 Javascript
JavaScript实现简单的星星评分效果
2017/05/18 Javascript
jQuery实现锚点向下平滑滚动特效示例
2017/08/29 jQuery
vue富文本编辑器组件vue-quill-edit使用教程
2018/09/21 Javascript
使用Python进行新浪微博的mid和url互相转换实例(10进制和62进制互算)
2014/04/25 Python
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
2014/06/10 Python
python脚本实现统计日志文件中的ip访问次数代码分享
2014/08/06 Python
解决Python requests 报错方法集锦
2017/03/19 Python
Python使用剪切板的方法
2017/06/06 Python
基于Python实现定时自动给微信好友发送天气预报
2018/10/25 Python
django session完成状态保持的方法
2018/11/27 Python
python使用pandas处理大数据节省内存技巧(推荐)
2019/05/05 Python
python多任务之协程的使用详解
2019/08/26 Python
keras自定义回调函数查看训练的loss和accuracy方式
2020/05/23 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
使用Python webdriver图书馆抢座自动预约的正确方法
2021/03/04 Python
Internet体系结构
2014/12/21 面试题
木工主管岗位职责
2013/12/08 职场文书
公司同意接收函
2014/01/13 职场文书
物理研修随笔感言
2014/02/14 职场文书
合作协议书
2014/04/23 职场文书
工作散漫检讨书
2014/09/16 职场文书
教师个人培训总结
2015/02/11 职场文书
Nginx服务器添加Systemd自定义服务过程解析
2021/03/31 Servers
python OpenCV学习笔记
2021/03/31 Python
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript
Python中with上下文管理协议的作用及用法
2022/03/18 Python
Java代码规范与质量检测插件SonarLint的使用
2022/08/05 Java/Android