1. 程式人生 > >http斷點續傳與檔案下載原理解析

http斷點續傳與檔案下載原理解析

 一、斷點續傳的原理

       其實斷點續傳的原理很簡單,就是在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"