讓PHP下載代碼支持斷點續(xù)傳,主要靠的 HTTP協(xié)議中header Content-Range來實現(xiàn).
先來說說 HTTP的下載原理
對于HTTP協(xié)議,向服務(wù)器請求某個文件時,只要發(fā)送類似如下的請求即可,代碼如下:
GET /Path/FileName HTTP/1.0
Host: www.server.com:80
Accept: **表示接收任何類型的數(shù)據(jù)。User-Agent表示用戶代理,這個字段可有可無,但強烈建議加上,因為它是服務(wù)器統(tǒng)計、追蹤以及識別客戶端的依據(jù)。Connection字段中的close表示使用非持久連接。
關(guān)于HTTP協(xié)議更多的細節(jié)可以參考RFC2616(HTTP 1.1),因為我只是想通過HTTP協(xié)議實現(xiàn)文件下載,所以也只看了一部分,并沒有看全。
如果服務(wù)器成功收到該請求,并且沒有出現(xiàn)任何錯誤,則會返回類似下面的數(shù)據(jù):
- HTTP/1.0 200 OK
- Content-Length: 13057672
- Content-Type: application/octet-stream
- Last-Modified: Wed, 10 Oct 2005 00:56:34 GMT
- Accept-Ranges: bytes
- ETag: "2f38a6cac7cec51:160c"
- Server: Microsoft-IIS/6.0
- X-Powered-By: ASP.NET
- Date: Wed, 16 Nov 2005 01:57:54 GMT
- Connection: close
先定義一個函數(shù) getRange() 這個函數(shù)用來處理 header中 Range 具體數(shù)據(jù)的處理,代碼如下:
- /** $file_size 文件大小 */
- function getRange($file_size){
- $range = isset($_SERVER['HTTP_RANGE'])?$_SERVER['HTTP_RANGE']:null;
- if(!emptyempty($range)){
- $range = preg_replace('/[s|,].*/', '', $range);
- $range = explode('-',substr($range,6));
- if (count($range) < 2 ) {
- $range[1] = $file_size;
- }
- $range = array_combine(array('start','end'),$range);
- if (emptyempty($range['start'])) {
- $range['start'] = 0;
- }
- if (!isset ($range['end']) || emptyempty($range['end'])) {
- $range['end'] = $file_size;
- }
- return $range;
- }
- return null;
- }
假設(shè)文件的地址為 $file_path,代碼如下:
- $speed = 512;//此參數(shù)為下載最大速度
- $pos = strrpos($file_path, "/");
- $file_name = substr($file_path, $pos+1);
- $file_size = filesize($file_path);
- $ranges = getRange($file_size);
- $fh = fopen($file_path, "rb");
- header('Cache-control: public');
- header('Content-Type: application/octet-stream');
- header('Content-Disposition: attachment; filename='.$file_name);
- if ($ranges != null) {
- header('HTTP/1.1 206 Partial Content');
- header('Accept-Ranges: bytes');
- header(sprintf('Content-Length: %u',$ranges['end'] - $ranges['start']));
- header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
- fseek($fh, sprintf('%u',$ranges['start']));
- }else{
- header("HTTP/1.1 200 OK");
- header(sprintf('Content-Length: %s', $file_size));
- }
- while(!feof($fh))
- {
- echo fread($fh, round($speed*1024, 0));
- ob_flush();
- sleep(1);
- }
- ($fh != null) && fclose($fh);
基本如此,就可以解決一般性文件的斷點續(xù)傳或者下載.
新聞熱點
疑難解答