PHP實現檔案下載斷點續傳詳解

scutephp發表於2017-01-01

如果我們的網站提供檔案下載的服務,那麼通常我們都希望下載可以斷點續傳(Resumable Download),也就是說使用者可以暫停下載,並在未來的某個時間從暫停處繼續下載,而不必重新下載整個檔案。

通常情況下,Web伺服器(如Apache)會預設開啟對斷點續傳的支援。因此,如果直接通過Web伺服器來提供檔案的下載,可以不必做特別的配置,即可享受到斷點續傳的好處。由於這些檔案直接通過Web伺服器來提供下載,後端指令碼無法對這個下載過程進行控制。這對於僅提供公開、靜態檔案的網站來說不是問題,但對於需要提供私有、動態檔案的網站來說,直接通過Web伺服器來提供下載就無法滿足需求了。這時,就需要在編寫後臺指令碼程式時,加入對斷點續傳的支援。

本文將以PHP為例,簡要介紹實現檔案下載斷點續傳的方法。

原理

斷點續傳的原理還是比較直觀的。

Http協議規定了如何傳輸某個資源的一部分,而不是全部。比如,有一個檔案的大小是1000位元組,瀏覽器可以只請求該檔案的前300個位元組,或者只請求第500到第1000個位元組。通過這種方式,就可以不必在一次請求中傳輸某個資源的全部內容,而是發起多次請求,每次僅請求其中的一部分內容。等所有這些請求都返回之後,再把得到的內容一塊一塊的拼接起來得到完整的資源。

實現斷點續傳就是要利用http協議的上述特性。當使用者暫停下載的時候,瀏覽器會記錄已經下載到什麼位置,當使用者在未來某一時間恢復下載時,就可以從上次暫停的位置繼續下載,而不必從頭開始。

實現

由於部分傳輸不是強制的,伺服器可以支援也可以不支援,所以,我們需要在程式中告訴瀏覽器,它請求的資源是否支援部分傳輸。這可以通過設定HTTP的 Accept-Ranges 響應頭資訊來實現。PHP程式碼如下:

程式碼如下:

header(`Accept-Ranges: bytes`);

Accept-Ranges: bytes 告訴瀏覽器,該資源支援以位元組為單位的部分傳輸。這個響應頭需要附加在支援部分傳輸的所有資源上。

當接受到一個請求時,我們需要從瀏覽器的請求中提取瀏覽器具體是在請求資源的哪一個部分。這個資訊是通過 Range 請求頭來傳遞的。在PHP中,它被儲存在$_SERVER[`HTTP_RANGE`]中。我們需要檢查這個變數是否定義了,如果定義了,則使用該值,否則,就將range設為整個資源。

程式碼如下:

$range = “0-“. ($content_length-1);
if(isset($_SERVER[`HTTP_RANGE`])){
    $range = $_SERVER[`HTTP_RANGE`];
}

接下來,就需要分析 $range 的值,來決定返回資源的哪一部分內容。可能的取值示例:

程式碼如下:

100-200 // 第100到第200位元組
500-    // 第500位元組到檔案末尾
-1000   // 最後的1000個位元組

這裡需要注意,得到一個Range之後,你需要對它的取值進行檢驗,包括:

1.開始位置非負
2.結束位置需要大於開始位置
3.開始位置需要小於檔案長度減一 (因為這裡的位置索引是從0開始的)
4.若結束位置大於檔案長度減一,則需要把它的值設定為檔案長度減一

如果Range的取值不合法,則需要終止程式並告知瀏覽器:

程式碼如下:

header(`HTTP/1.1 416 Requested Range Not Satisfiable`);

為了保持文章簡潔,具體的校驗程式碼這裡就不提供了。下面假定你已經校驗了Range的取值,並得到了 $start 和 $end 兩個變數,分別表示開始位置和結束位置。

接下來要做的就是把檔案的對應部分的內容傳送給瀏覽器。不過要注意的是,這裡涉及到需要傳送多個HTTP響應頭資訊,具體如下:

程式碼如下:

header(`HTTP/1.1 206 Partial Content`);
header(`Accept-Ranges: bytes`);
header(“Content-Range: bytes $start-$end/$filesize”);
$length = $end – $start + 1;
header(“Content-Length: $length”);

/ 輸出檔案的指定部分 /

這裡的$length需要注意一下,它的取值是本次傳輸的內容的長度,而不是整個檔案的長度。另外需要注意的一點是,這裡的HTTP狀態碼是206,不是200。

總結

檔案下載的斷點續傳實際上是利用了HTTP協議中對傳輸部分檔案的支援。而HTTP協議的這一特性不僅可以用於實現斷點續傳,客戶端程式也可以利用它來實現多執行緒下載。

在實現斷點續傳的過程中,需要注意正確設定各種HTTP頭資訊。錯誤的頭資訊將導致使用者下載到的檔案損壞,無法使用。

原文連結:http://www.kubiji.cn/juhe-id3146.html


相關文章