當用戶從靜態文件服務器上獲取諸如歌曲這樣的流媒體文件時,如果網絡連接斷開,重連后未做處理,就需要重新下載這個文件。所以為了避免這種情況,我們的服務器需要一種斷點續傳的功能。而http 1.1中正好規定了一種
Range
機制,我們可以通過這種機制來進行分片傳輸。
Range
當一個服務器支持Range
時,客戶端可以將需要發送的內容分成很多份發送給服務端,服務端可以每次接收部分內容。有了這樣的能力,遇到斷網的情況,我們可以在客戶端記錄下已經傳送的文件范圍,網絡恢復后再將剩余部分發送給服務端,這樣就實現了斷點續傳。
Range
的在http 1.1中的具體定義可以參考文檔:
具體流程如下:
瀏覽器請求內容。
-
服務器告訴瀏覽器,該內容可以使用 Accept-Ranges 消息頭進行分部分請求。
response.setHeader('Accept-Ranges', 'bytes');
-
瀏覽器重新發送請求,用 Range 消息頭告訴服務器需要的內容范圍。
發送的Range格式:字節數(bytes)= (開始)-(結束)
這是瀏覽器告知服務器所需分部分內容范圍的消息頭. 注意開始和結束位置是都包括在內的,而且是從0開始的. 這個消息頭也可以不發送兩個位置,其含義如下:
- 如果結束位置被去掉了,服務器會返回從聲明的開始位置到整個內容的結束位置內容的最后一個可用字節。
- 如果開始位置被去掉了,結束位置參數可以被描述成從最后一個可用的字節算起可以被服務器返回的字節數。
而服務器會分如下兩種情況響應瀏覽器的請求:
- 如果范圍是合理的,服務器會返回所請求的部分內容,并帶上 206 Partial Content 狀態碼. 當前內容的范圍會在 Content-Range 消息頭中申明。
發送的Content-Range格式:字節數(bytes)=(開始)-(結束)/(總數) - 如果范圍是不可用的(例如,比內容的總字節數大), 服務器會返回 416 請求范圍不合理 Requested Range Not Satisfiable 狀態碼. 可用的范圍也會在 Content-Range 消息頭中聲明。
nodejs簡單實現
getStream(req, res, filepath, statObj) {
let start = 0;
let end = statObj.size - 1;
let range = req.headers['range'];
if (range) {
res.setHeader('Accept-Range', 'bytes');
res.statusCode = 206;
let result = range.match(/bytes=(\d*)-(\d*)/);
if (result) {
start = isNaN(result[1]) ? start : parseInt(result[1]);
end = isNaN(result[2]) ? end : parseInt(result[2]) - 1;
}
}
return fs.createReadStream(filepath, {
start, end
});
}
待續
自我小結
在搭建node靜態服務器過程中學習利用Http1.1的Range
來實現斷點續傳功能