http斷點續傳與檔案下載原理解析
阿新 • • 發佈:2019-02-15
一、斷點續傳的原理
其實斷點續傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。
打個比方,瀏覽器請求伺服器上的一個文時,所發出的請求如下:
?
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位元組開始傳,前面的位元組不用傳了。
伺服器收到這個請求以後,返回的資訊如下:
?
206
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"
|