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 相关文章推荐
php创建多级目录代码
Jun 05 PHP
PHP编程函数安全篇
Jan 08 PHP
解析php取整的几种方式
Jun 25 PHP
完善CodeIgniter在IDE中代码提示功能的方法
Jul 19 PHP
WordPress中获取页面链接和标题的相关PHP函数用法解析
Dec 17 PHP
PHP+JS三级菜单联动菜单实现方法
Feb 24 PHP
PHP实现动态执行代码的方法
Mar 25 PHP
Yii2 输出xml格式数据的方法
May 03 PHP
Yii+MYSQL锁表防止并发情况下重复数据的方法
Jul 14 PHP
php微信开发之谷歌测距
Jun 14 PHP
实例讲解PHP验证邮箱是否合格
Jan 28 PHP
PHP中__set()实例用法和基础讲解
Jul 23 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
浅谈apache和nginx的rewrite的区别
2013/02/22 PHP
PHP制作登录异常ip检测功能的实例代码
2016/11/16 PHP
关于图片验证码设计的思考
2007/01/29 Javascript
JavaScript Event学习第十一章 按键的检测
2010/02/10 Javascript
JS实现文档加载完成后执行代码
2015/07/09 Javascript
jquery实现像栅栏一样左右滑出式二级菜单效果代码
2015/08/24 Javascript
Node.js的Mongodb使用实例
2016/12/30 Javascript
jQuery快速实现商品数量加减的方法
2017/02/06 Javascript
AngularJS之自定义服务详解(factory、service、provider)
2017/04/14 Javascript
js使用highlight.js高亮你的代码
2017/08/18 Javascript
JS动画定时器知识总结
2018/03/23 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
微信小程序如何调用图片接口API并居中显示
2019/06/29 Javascript
vue+element项目中过滤输入框特殊字符小结
2019/08/07 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
2019/09/23 Javascript
浅谈vuex中store的命名空间
2019/11/08 Javascript
Vue-cli4 配置 element-ui 按需引入操作
2020/09/11 Javascript
JavaScript实现打字游戏
2021/02/19 Javascript
vue实现拖拽进度条
2021/03/01 Vue.js
[36:17]DOTA2上海特级锦标赛 - VGL音乐会全集
2016/03/06 DOTA
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python 闭包的使用方法
2017/09/07 Python
谈谈python中GUI的选择
2018/03/01 Python
python购物车程序简单代码
2018/04/18 Python
详解Python静态网页爬取获取高清壁纸
2019/04/23 Python
Python操作Mongodb数据库的方法小结
2019/09/10 Python
安装PyInstaller失败问题解决
2019/12/14 Python
Pycharm打开已有项目配置python环境的方法
2020/07/03 Python
python性能测试工具locust的使用
2020/12/28 Python
美国女性服饰销售网站:Nasty Gal(坏女孩)
2016/07/26 全球购物
The North Face北面美国官网:美国著名户外品牌
2018/09/15 全球购物
索引覆盖(Index Covering)查询含义
2012/02/18 面试题
如何手工释放资源
2013/12/15 面试题
文明市民先进事迹
2014/05/15 职场文书
五四青年节活动总结
2015/02/10 职场文书
创业计划书之校园超市
2019/09/12 职场文书