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


    <?
    
    /**
     @author Nguyen Quoc Bao <quocbao.coder@gmail.com>
     @version 1.3
     @desc A simple object for processing download operation , support section downloading
     Please send me an email if you find some bug or it doesn't work with download manager.
     I've tested it with
     	- Reget
     	- FDM
     	- FlashGet
     	- GetRight
     	- DAP
     	
     @copyright It's free as long as you keep this header .
     @example
     
     1: File Download
     	$object = new downloader;
     	$object->set_byfile($filename); //Download from a file
     	$object->use_resume = true; //Enable Resume Mode
     	$object->download(); //Download File
     	
     2: Data Download
      $object = new downloader;
     	$object->set_bydata($data); //Download from php data
     	$object->use_resume = true; //Enable Resume Mode
     	$object->set_filename($filename); //Set download name
     	$object->set_mime($mime); //File MIME (Default: application/otect-stream)
     	$object->download(); //Download File
     	
     	3: Manual Download
     	$object = new downloader;
     	$object->set_filename($filename);
    	$object->download_ex($size);
    	//output your data here , remember to use $this->seek_start and $this->seek_end value :)
    	
    **/
    
    class HttpDownload {
    
    	var $data = null;
    	var $data_len = 0;
    	var $data_mod = 0;
    	var $data_type = 0;
    	var $data_section = 0; //section download
    	/**
    	 * @var ObjectHandler
    	 **/
    	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;
    	
    	/**
    	 * Total bandwidth has been used for this download
    	 * @var int
    	 */
    	var $bandwidth = 0;
    	/**
    	 * Speed limit
    	 * @var float
    	 */
    	var $speed = 0;
    	
    	/*-------------------
    	| Download Function |
    	-------------------*/
    	/**
    	 * Check authentication and get seek position
    	 * @return bool
    	 **/
    	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;
    		}
    		
    		return true;
    	}
    	/**
    	 * Send download information header
    	 **/
    	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;
    	}
    	
    	/**
    	 * Start download
    	 * @return bool
    	 **/
    	function download() {
    		if (!$this->initialize()) return false;
    		
    		$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;
    				}
    				else
    				{
    					echo fread($res , $bufsize);
    					$this->bandwidth += $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;
    				}
    				else
    				{
    					$this->bandwidth += $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->use_autoexit) exit();
    		
    		//restore old status
    		ignore_user_abort($old_status);
    		set_time_limit(ini_get("max_execution_time"));
    		
    		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);
    			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;
    	}
    	
    	/**
    	 * Check authentication
    	 * @return bool
    	 **/
    	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
    	}
    	
    }
    
    ?>

    自定义函数

    /************************************************************************
    * 函数名称:httpDownload
    * 函数说明:文件下载
    * 输入参数:
    $filename 另存文件名
    $type 下载类型 0下载文件 1下载数据 2直接URL下载
    $data 下载数据
    $mime 响应正文类型,默认application/octet-stream
    * 返 回 值:逻辑型 true|false
    * 编 写 者:李小宇
    * 编写时间:2011/8/10
    *************************************************************************
    */
    function httpDownload($filename, $type, $data='', $mime='') {
    try {
    if(!class_exists("HttpDownload")) {
    include_once(dirname(__FILE__)."/class/HttpDownload.class.php");
    }
    $obj = new HttpDownload();
    //设置默认属性
    $obj->use_resume = true;
    if(!empty($mime)) {
    $obj->set_mime($mime);
    }
    if(0 == $type) {
    $obj->set_byfile($filename);
    }
    elseif(1 == $type) {
    $obj->set_bydata($data);
    $obj->set_filename($filename);
    }
    elseif(2 == $type) {
    $obj->set_byurl($filename);
    }
    $obj->download();
    return true;
    }
    catch ( Exception $e ) {
    $msg = $e->getMessage();
    saveLog(
    $msg, __FILE__ );
    return false;
    }
    }

      

  • 相关阅读:
    最大子数组
    链表插入排序
    链表求和
    有效回文串
    排球比赛计分系统
    超市收银系统
    三层架构
    Wpf+数据库代码封装+策略模式封装
    封装逻辑用策略模式实现
    代码封装
  • 原文地址:https://www.cnblogs.com/phpfans/p/2133530.html
Copyright © 2020-2023  润新知