2022年5月2日 星期一

HTTP傳輸大檔案原理

有三種方法可以縮短通過 HTTP 發送大量資料的時間:

  • 壓縮資料
  • 發送區塊資料
  • 請求選定範圍內的資料


以上三種方法可以組合起來一起使用。在 HTTP 1.1 版引入了區塊資料來幫助處理大量資料情況。


HTTP server 在發送 response 時,會添加一個header, Transfer-Encoding: chunked,讓瀏覽器知道資料是以區塊的形式傳輸。


每個區塊資料由以下部分組成:

  • 區塊資料長度
  • 區塊資料
  • 區塊結尾的 CRLF 分隔符


server持續將區塊資料傳輸到瀏覽器。當到達資料流的末尾時,它會附加一個由以下部分組成的結束標記:

  • 一個長度為 0 的區塊,末尾有一個 CRLF
  • 額外的 CRLF


瀏覽器會等待所有資料區塊,直到收到結束標記。然後它會刪除區塊編碼,包括 CRLF 和長度信息,將區塊資料組合成,最後成為一份完整的資料。


對於像 5GB 這樣大小的視頻,完整的資料仍然需要一段時間才能完全到達。

我們可以先獲取選定的部分,並在需要時再請求其他部分。例如在 YouTube 上打開一個視頻,會看到一個灰色的進度條正在向前移動。那是 YouTube 請求選定範圍內的資料。這個功能讓使用者可以在時間軸中的任意位置跳轉。當點擊進度條上的點時,瀏覽器將請求特定範圍的視頻資料。


在server上實現範圍請求功能是選擇性實作的。可以在 response header 中找到 Accept-Ranges: bytes。在 YouTube 請求中,任何“播放”請求,都可以找到一個標頭範圍請求,看起來像 Range: bytes=0-80,並且是 0-indexed。


假設一個資料總共有 100 個字節。

  • Range: bytes=20 請求從 20 到結尾的範圍,等於 Range: bytes=20-99。
  • Range: bytes=-20 請求最後 20 個字節的資料,等於 Range: bytes=80-99。


如果請求的範圍有效,則 server 發送帶有 Content-Range 、驗證資料範圍和總長度的標頭,例如 Content-Range:bytes 70-80/100。


Range request 廣泛用於視頻流和文件下載,在網路中斷後繼續下載文件是一個使用的例子。


範圍請求支持多個範圍,例如,可以從文件中請求兩個範圍:bytes=20-45, 70-80。


multi-range 看起來類似於區塊資料。每個資料包含以下部分:

  • 一個邊界(boundary)區塊,指示資料的邊界,以 -- 開頭、 CRLF 結尾
  • 兩個header,Content-Type和Content-Range,表示相對應的資料區塊的屬性,以CRLF結尾
  • 一個額外的 CRLF 告訴客戶端真正的資料即將到來
  • 最後,以 CRLF 結尾的資料區塊


boundary 只是一個看起來像 3d6b6a416f9b5 的隨機字符串,標記不同資料區塊的邊界。最終,主體以一個邊界區塊結束,以一個 -- 開始,以 -- 和一個 CRLF 結束。這部分告訴瀏覽器分為多個部份的資料已經結束。

沒有留言:

張貼留言