一、斷點續傳的原理
其實斷點續傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。
打個比方,浏覽器請求服務器上的一個文時,所發出的請求如下:
假設服務器域名為www.jizhuomi.com/android,文件名為down.zip。
get /down.zip http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)
connection: keep-alive
服務器收到請求後,按要求尋找請求的文件,提取文件的信息,然後返回給浏覽器,返回信息如下:
content-length=106786028
accept-ranges=bytes
date=mon, 30 apr 2001 12:56:11 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:56:11 gmt
所謂斷點續傳,也就是要從文件已經下載的地方開始繼續下載。所以在客戶端浏覽器傳給web服務器的時候要多加一條信息--從哪裡開始。
下面是用自己編的一個“浏覽器”來傳遞請求信息給web服務器,要求從2000070字節開始。
get /down.zip http/1.0
user-agent: netfox
range: bytes=2000070-
accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
仔細看一下就會發現多了一行 range: bytes=2000070-
這一行的意思就是告訴服務器down.zip這個文件從2000070字節開始傳,前面的字節不用傳了。
服務器收到這個請求以後,返回的信息如下:
content-length=106786028
content-range=bytes 2000070-106786027/106786028
date=mon, 30 apr 2001 12:55:20 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:55:20 gmt
和前面服務器返回的信息比較一下,就會發現增加了一行:
content-range=bytes 2000070-106786027/106786028
返回的代碼也改為206了,而不再是200了。
知道了以上原理,就可以進行斷點續傳的編程了。
二.文件下載和在浏覽器顯示
文件下載原理主要控制來自於服務器端響應,浏覽器或者httpClient自行讀取IO流
Accept-Ranges:bytes #接受類型
Access-Control-Allow-Origin:* #允許任何主機均可跨域訪問,ajax同樣可以
Access-Control-Max-Age:2592000
Cache-Control:public, max-age=31536000
Connection:keep-alive
Content-Disposition:attachment; filename="c501b_01_h264_sd_960_540.mp4"
Content-Length:14470485
Content-Transfer-Encoding:binary #傳輸類型,字節類型
Content-Type:video/mp4 #響應類型
Date:Sun, 25 Jan 2015 00:17:14 GM #文件日期--注意,對於浏覽器讀取緩存而不重新請求服務器十分有用,用來檢測靜態文件有沒有被修改
ETag:"lraEcGPNv-73F2tLNOKhuA8a6pFa" #
下面是一個簡單的好PHP下載實例
<?php
$file_name="哈哈.jpg";//需要下載的文件
$file_name=iconv("utf-8","gb2312","$file_name");
$fp=fopen($file_name,"r+");//下載文件必須先要將文件打開,寫入內存
if(!file_exists($file_name)){//判斷文件是否存在
echo "文件不存在";
exit();
}
$file_size=filesize("a.jpg");//判斷文件大小
//返回的文件
Header("Content-type: application/octet-stream");
//按照字節格式返回
Header("Accept-Ranges: bytes");
//返回文件大小
Header("Accept-Length: ".$file_size);
//彈出客戶端對話框,對應的文件名
Header("Content-Disposition: attachment; filename=".$file_name);
//防止服務器瞬時壓力增大,分段讀取
$buffer=1024;
while(!feof($fp)){
$file_data=fread($fp,$buffer);
echo $file_data;
}
//關閉文件
fclose($fp);
?>
三.關於在浏覽器中顯示文件內容
浏覽器默認會顯示一些 text/*,image/*,PDF類型的文件,但默認會變成自動下載,這是我們需要修改響應頭為
Content-Disposition:inline; filename="c501b_01_h264_sd_960_540.mp4"