这里只展示了核心代码部分,使用了封装request和response的gin框架,若小伙伴没使用可用改成go自带的http。
func SendFile(r *gin.Context) {
//断点续传标志
var range_ext = r.GetHeader("Range")
filePath := "." + r.Request.URL.Path
if filePath == "./" {
filePath = "./index.html"
}
parts := strings.Split(filePath, ".")
print(parts[len(parts)-1] + "\n")
print(filePath + "\n")
file1, _ := os.Open(filePath)
data, _ := ioutil.ReadAll(file1)
//获取content type
contentType := extensionToContentType[parts[len(parts)-1]]
print(contentType + "\n")
if file1 == nil {
r.HTML(404, "404.html", gin.H{})
return
}
var FileStreamSize int64 = r.Request.ContentLength
if FileStreamSize == 0 {
fi, _ := file1.Stat()
FileStreamSize = fi.Size()
}
var FileStreamLen string = strconv.FormatInt(FileStreamSize, 10)
//Range字段为空, 直接发送数据
if range_ext == "" {
r.Writer.Header().Set("Content-Type", contentType)
r.Writer.Header().Set("Content-Length", FileStreamLen)
r.Writer.WriteHeader(200)
r.Writer.Write(data)
return
}
//Range字段非空,断点续传模式
fmt.Printf("part download...\n")
fmt.Printf("head range is:%s\n", range_ext)
length := strings.Index(range_ext, "=")
allRange := range_ext[length+1:]
remove := strings.Index(allRange, "-")
prelen := allRange[:remove]
behind := allRange[remove+1:]
var start int64
var end int64
if prelen == "" {
behindint, _ := strconv.ParseInt(behind, 10, 64)
start = FileStreamSize - behindint
end = FileStreamSize
FileStreamLen = behind
}
if behind == "" {
prelenint, _ := strconv.ParseInt(prelen, 10, 64)
start = prelenint
end = FileStreamSize
FileStreamLen = strconv.FormatInt(end-start, 10)
}
if prelen != "" && behind != "" {
prelenint, _ := strconv.ParseInt(prelen, 10, 64)
behindint, _ := strconv.ParseInt(behind, 10, 64)
start = prelenint
end = behindint
FileStreamLen = strconv.FormatInt(end-start+1, 10)
}
allRange = allRange + strconv.FormatInt(FileStreamSize, 10)
fmt.Printf("start:%v, end:%v, allRange:%v, FileSize:%v, FileLen:%v\n", start, end, allRange, FileStreamSize, FileStreamLen)
r.Writer.Header().Set("Content-Type", contentType)
r.Writer.Header().Set("Accept-Ranges", "bytes")
r.Writer.Header().Set("Content-Length", FileStreamLen)
r.Writer.Header().Set("Content-Range", "bytes "+allRange+"/"+strconv.FormatInt(FileStreamSize, 10))
r.Writer.WriteHeader(206)
r.Writer.Write(data[start:end])
fmt.Println("file Wirte finished")
}