php 支持斷點續傳,主要依靠HTTP協議中 header HTTP_RANGE實現。
HTTP斷點續傳原理
Http頭 Range、Content-Range()
HTTP頭中一般斷點下載時才用到Range和Content-Range實體頭,
Range用戶請求頭中,指定第一個字節的位置和最後一個字節的位置,如(Range:200-300)
Content-Range用於響應頭
請求下載整個文件:
GET /test.rar HTTP/1.1
Connection: close
Host: 116.1.219.219
Range: bytes=0-801 //一般請求下載整個文件是bytes=0- 或不用這個頭
一般正常回應
HTTP/1.1 200 OK
Content-Length: 801
Content-Type: application/octet-stream
Content-Range: bytes 0-800/801 //801:文件總大小
FileDownload.class.php
<?php /** php下載類,支持斷點續傳 * Date: 2013-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * download: 下載文件 * setSpeed: 設置下載速度 * getRange: 獲取header中Range */ class FileDownload{ // class start private $_speed = 512; // 下載速度 /** 下載 * @param String $file 要下載的文件路徑 * @param String $name 文件名稱,為空則與下載的文件名稱一樣 * @param boolean $reload 是否開啟斷點續傳 */ public function download($file, $name='', $reload=false){ if(file_exists($file)){ if($name==''){ $name = basename($file); } $fp = fopen($file, 'rb'); $file_size = filesize($file); $ranges = $this->getRange($file_size); header('cache-control:public'); header('content-type:application/octet-stream'); header('content-disposition:attachment; filename='.$name); if($reload && $ranges!=null){ // 使用續傳 header('HTTP/1.1 206 Partial Content'); header('Accept-Ranges:bytes'); // 剩余長度 header(sprintf('content-length:%u',$ranges['end']-$ranges['start'])); // range信息 header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size)); // fp指針跳到斷點位置 fseek($fp, sprintf('%u', $ranges['start'])); }else{ header('HTTP/1.1 200 OK'); header('content-length:'.$file_size); } while(!feof($fp)){ echo fread($fp, round($this->_speed*1024,0)); ob_flush(); //sleep(1); // 用於測試,減慢下載速度 } ($fp!=null) && fclose($fp); }else{ return ''; } } /** 設置下載速度 * @param int $speed */ public function setSpeed($speed){ if(is_numeric($speed) && $speed>16 && $speed<4096){ $this->_speed = $speed; } } /** 獲取header range信息 * 查看本欄目