IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> HTTP 断点续传及其基于 PHP 的实现方案
猫猫草
post 2009-09-22 15:54:50, Tue
Post #1


猫猫猫
***

Group: Power Cat
Posts: 626
Joined: 2006-12-8
Member No.: 2



引用
断点续传是我们现在经常接触的概念,那么HTTP协议是如何支持断点续传的呢。我们先从一个例子来看看。
下面是一个断点续传的例子:(使用NetVampire得到)
I01-7-1219:19:23-------------------------Attempt1-------------------------
P01-7-1219:19:24Connectingto127.0.0.3...
P01-7-1219:19:24Connectedto127.0.0.3[127.0.0.3]S01-7-1219:19:24GET/VS0515AI.EXEHTTP/1.1
S01-7-1219:19:24Connection:close
S01-7-1219:19:24Host:127.0.0.3
S01-7-1219:19:24Accept:*/*
S01-7-1219:19:24Pragma:no-cache
S01-7-1219:19:24Cache-Control:no-cache
S01-7-1219:19:24Referer:http://127.0.0.3/
S01-7-1219:19:24User-Agent:Mozilla/4.04[en](Win95;I;Nav)
S01-7-1219:19:24
R01-7-1219:19:24HTTP/1.1200OK
R01-7-1219:19:24Server:ZeroHttpServer/1.0
R01-7-1219:19:24Date:Thu,12Jul200111:19:24GMT
R01-7-1219:19:24Cache-Control:no-cache
R01-7-1219:19:24Last-Modified:Tue,30Jan200113:11:30GMT
R01-7-1219:19:24Content-Type:application/octet-stream
R01-7-1219:19:24Content-Length:15143086
R01-7-1219:19:24Connection:close
R01-7-1219:19:24
P01-7-1219:19:25Datatransferstarted
I01-7-1219:19:32JobStoppedbyuser
I01-7-1219:19:33Received5275648bytesin0:00:07(691435bytes/s)
I01-7-1219:19:40-------------------------Attempt2-------------------------
P01-7-1219:19:40Connectingto127.0.0.3...
P01-7-1219:19:40Connectedto127.0.0.3[127.0.0.3]
S01-7-1219:19:40GET/VS0515AI.EXEHTTP/1.1
S01-7-1219:19:40Connection:close
S01-7-1219:19:40Host:127.0.0.3
S01-7-1219:19:40Accept:*/*
S01-7-1219:19:40Pragma:no-cache
S01-7-1219:19:40Cache-Control:no-cache
S01-7-1219:19:40Referer:http://127.0.0.3/
S01-7-1219:19:40User-Agent:Mozilla/4.04[en](Win95;I;Nav)
S01-7-1219:19:40Range:bytes=5275648-
S01-7-1219:19:40
R01-7-1219:19:40HTTP/1.1206PartialContent
R01-7-1219:19:40Server:ZeroHttpServer/1.0
R01-7-1219:19:40Date:Thu,12Jul200111:19:40GMT
R01-7-1219:19:40Cache-Control:no-cache
R01-7-1219:19:40Last-Modified:Tue,30Jan200113:11:30GMT
R01-7-1219:19:40Content-Type:application/octet-stream
R01-7-1219:19:40Content-Range:bytes5275648-15143085/15143086
R01-7-1219:19:40Content-Length:9867438
R01-7-1219:19:40Connection:close
R01-7-1219:19:40
P01-7-1219:19:40Datatransferstarted
I01-7-1219:19:41JobStoppedbyuser
I01-7-1219:19:41Received1124756bytesin0:00:01(969617bytes/s)
第一次是普通的传输;第二次由于没有传完全,就发出了Range这个头部,从5275648字节开始传输(默认是按字节算),回应使用206状态值,表示现在开始部分传输,回复Content-Length头部,表示传输的部分,用字节记,然后就与普通传输没有区别了。
Go to the top of the page
 
+Quote Post
猫猫草
post 2009-09-22 15:55:50, Tue
Post #2


猫猫猫
***

Group: Power Cat
Posts: 626
Joined: 2006-12-8
Member No.: 2



断点续传指的是在上传时,将上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传,下面我们来看看php 断点续传功能的实现方法吧。
代码
<?php
/**
    * 作者 于恩水<yuenshui@126.com>
    * 支持断点续传下载
    * 实例代码:
    *           $down = new SD_DownLoad();
    *          $down->Down('E:/iso/MS.Office2003SP1.CHS.iso');
    **/
class SD_DownLoad {
    
     /**
         * 下载的开始点
         *
         * @access private
         * @var integer
         */
     private $mDownStart;
    
     /**
         * 文件大小
         *
         * @access private
         * @var integer
         */
     private $mFileSize;
    
     /**
         * 文件句柄
         *
         * @access private
         * @var integer
         */
     private $mFileHandle;
    
     /**
         * 文件全路径
         *
         * @access private
         * @var string
         */
     private $mFilePath;
    
     /**
         * 文件下载时显示的文件名
         *
         * @access private
         * @var string
         */
     private $mFileName;
    
     /**
         * 构造函数
         *
         * @access public
         * @return void
         **/
     public function __construct() {
     }
    
     /**
         * 下载
         *
         * @param string $pFilePath 文件全路径
         * @param string pFileName 文件下载时显示的文件名,缺省为实际文件名
         * @access public
         * @return void
         **/
     public function Down($pFilePath, $pFileName = '') {
          $this->mFilePath = $pFilePath;
          if(!$this->IniFile()) $this->SendError();
          $this->mFileName = empty($pFileName) ? $this->GetFileName() : $pFileName;
        
          $this->IniFile();
          $this->SetStart();
          $this->SetHeader();
        
          $this->Send();
     }

    
     /**
         * 初始化文件信息
         *
         * @access private
         * @return boolean
         **/
     private function IniFile() {
          if(!is_file($this->mFilePath)) return false;
          $this->mFileHandle = fopen($this->mFilePath, 'rb');
          $this->mFileSize = filesize($this->mFilePath);
          return true;
     }
    
     /**
         * 设置下载开始点
         *
         * @access private
         * @return void
         **/
     private function SetStart() {
          if (!empty($_SERVER['HTTP_RANGE']) && preg_match("/^bytes=([d]?)-([d]?)$/i", $_SERVER['HTTP_RANGE'], $match)) {
               if(empty($match[1])) $this->mDownStart = $match[1];
               fseek($this->mFileHandle, $this->mDownStart);
          }
          else {
               $this->mDownStart = 0;
          }
     }
    
     /**
         * 设置http头
         *
         * @access private
         * @return void
         **/
     private function SetHeader() {
          @header("Cache-control: public");
          @header("Pragma: public");
          Header("Content-Length: " . ($this->mFileSize - $this->mDownStart));
          if ($this->mDownStart > 0) {
               @Header("HTTP/1.1 206 Partial Content");
               Header("Content-Ranges: bytes" . $this->mDownStart . "-" . ($this->mFileSize - 1) . "/" . $this->mFileSize);
          }
          else {
               Header("Accept-Ranges: bytes");
          }
          @header("Content-Type: application/octet-stream");
          @header("Content-Disposition: attachment;filename=" . $this->mFileName);
     }
    
     /**
         * 获取全路径里的文件名部分
         *
         * @access private
         * @return string
         **/
     private function GetFileName() {
          return basename ($this->mFilePath);
     }
    
     /**
         * 发送数据
         *
         * @access private
         * @return void
         **/
     private function Send() {
          fpassthru($this->mFileHandle);
     }
    
     /**
         * 发送错误
         *
         * @access public
         * @return void
         **/
     public function SendError() {
          @header("HTTP/1.0 404 Not Found");
          @header("Status: 404 Not Found");
          exit();
     }
}
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



Lo-Fi Version Time is now: 2024-10-17 02:54