原文地址:https://www.yuque.com/yss930819/guqz9f/aly0lz
golang #程式碼片段 #檔案服務 #下載 #goframe
檔案的斷點續傳,需要使用到 HTTP 協議的 206 狀態碼 實現檔案的斷點續傳,具體的原理在網上可以找到一堆。網上找的所有 golang 程式碼都缺少一個步驟 flush 即將檔案的內容寫入後應主動將內容傳送到客戶端 即程式碼 39行 內容。
在研究了 java 的實現後,發現所有的 golang 實現都沒有用 flush 不知道是 golang 本身提供的 net/http 裡的 writer 已經實現了寫入即 flush 的功能。
我們使用的 goframe 框架進行開發,在斷點續傳時需要做如下處理。PS:已使用迅雷和
參考的網站有
https://www.cnblogs.com/peteremperor/p/14081050.html
https://blog.csdn.net/zgh670042085/article/details/84416227
func download(r *ghttp.Request) {
f,_ := gfile.Open("D:\\Windows.iso")
info, _:= f.Stat()
r.Response.Header().Add("Accept-Ranges", "bytes")
r.Response.Header().Add("Content-Disposition", "attachment; filename="+info.Name())
var start, end int64
//fmt.Println(request.Header,"\n")
if rangeBytes := r.Header.Get("Range"); rangeBytes != "" {
if strings.Contains(rangeBytes, "bytes=") && strings.Contains(rangeBytes, "-") {
fmt.Sscanf(rangeBytes, "bytes=%d-%d", &start, &end)
if end == 0 {
end = info.Size() - 1
}
r.Response.Header().Add("Content-Length", strconv.FormatInt(end-start+1, 10))
r.Response.Header().Add("Content-Range", fmt.Sprintf("bytes %v-%v/%v", start, end, info.Size()))
r.Response.WriteHeader(http.StatusPartialContent)
} else {
r.Response.WriteHeader(http.StatusBadRequest)
return
}
} else {
r.Response.Header().Add("Content-Length", strconv.FormatInt(info.Size(), 10))
start = 0
end = info.Size() - 1
}
_, _ = f.Seek(start, 0)
n := 1024 * 1024
buf := make([]byte, n)
for {
if end-start+1 < int64(n) {
n = int(end - start + 1)
}
_, err := f.Read(buf[:n])
if err != nil {
}
err = nil
r.Response.Write(buf[:n])
r.Response.Flush()
start += int64(n)
if start >= end+1 {
return
}
}
}