這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
- https://github.com/artificerpi/oget
HTTP Range 請求
HTTP Range請求允許伺服器向用戶端發送HTTP訊息體的一部分資料。Partial Requests在使用比較大的網路媒體檔案或者在下載檔案時提供暫停和恢複功能時很有用。
這也是下載時實現HTTP斷點續傳的一個關鍵。
HTTP 206 (Partial Content)
如果伺服器能返回HTTP 206請求,我們就知道它能夠支援Range request.
# curl -I https://www.baidu.com/ -H "Range: bytes=0-"HTTP/1.1 206 Partial ContentCache-Control: private, no-cache, no-store, proxy-revalidate, no-transformConnection: Keep-AliveContent-Length: 277Content-Range: bytes 0-276/277Content-Type: text/htmlDate: Mon, 25 Dec 2017 15:29:35 GMTEtag: "575e1f71-115"Last-Modified: Mon, 13 Jun 2016 02:50:25 GMTPragma: no-cacheServer: bfe/1.0.8.18
go代碼
req, err := http.NewRequest(http.MethodHead, f.URL, nil)if err != nil { log.Fatalf("Invalid url for downloading: %s, error: %v", f.URL, err)}req.Header.Set("Range", "bytes=0-")client := &http.Client{ Timeout: time.Second * 5,}resp, err := client.Do(req)if err != nil { log.Fatal(err)}defer resp.Body.Close() switch resp.StatusCode {case http.StatusPartialContent: rangeSatisfiable = true log.Println("Partial Content is supported.")case http.StatusOK, http.StatusRequestedRangeNotSatisfiable: log.Println(f.URL, "does not support for range request.")default: log.Fatal("Got unexpected status code", resp.StatusCode) return}
Range 要求標頭
我們可以使用Range要求標頭,告訴伺服器應該返回給用戶端的內容部分。
# 通常<unit>為 bytesRange: <unit>=<range-start>-Range: <unit>=<range-start>-<range-end>Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
代碼實現
req, err := http.NewRequest(http.MethodGet, f.URL, nil)if err != nil { return} // s.String()實現: fmt.Sprintf("bytes=%d-%d", h.StartPos, h.EndPos)req.Header.Set("Range", s.String())client := &http.Client{}resp, err := client.Do(req)if err != nil { return}defer resp.Body.Close()data, err := ioutil.ReadAll(resp.Body)
Seek and Write
最後類似於Java中的RandAccessFile, 我們可以使用io.WriteAt (推薦,使用介面更好,也容易測試)或者直接用檔案控制代碼寫n, err := f.FileHandler.WriteAt(data, int64(s.StartPos))
具體實現請訪問oget ,歡迎交流和分享。