【发布时间】:2021-03-24 12:47:42
【问题描述】:
我在 Github 上建立了一个基础项目:https://github.com/kounelios13/range-download。 本质上,这个项目尝试使用 HTTP Range 请求下载文件,组装它,然后将其保存回磁盘。我正在尝试关注this article(暂时除了goroutines)。当我尝试使用范围请求下载文件时,在合并所有请求数据后,最终大小大于我将获得的原始大小并且最终文件已损坏。
这里是负责下载文件的代码
type Manager struct{
limit int
}
func NewManager(limit int) *Manager{
return &Manager{
limit: limit,
}
}
func (m *Manager) DownloadBody(url string ) ([]byte ,error){
// First we need to determine the filesize
body := make([]byte ,0)
response , err := http.Head(url) // We perform a Head request to get header information
if response.StatusCode != http.StatusOK{
return nil ,fmt.Errorf("received code %d",response.StatusCode)
}
if err != nil{
return nil , err
}
maxConnections := m.limit // Number of maximum concurrent co routines
bodySize , _ := strconv.Atoi(response.Header.Get("Content-Length"))
bufferSize :=(bodySize) / (maxConnections)
diff := bodySize % maxConnections
read := 0
for i:=0;i<maxConnections;i++{
min := bufferSize * i
max := bufferSize * (i+1)
if i==maxConnections-1{
max+=diff // Check to see if we have any leftover data to retrieve for the last request
}
req , _ := http.NewRequest("GET" , url, nil)
req.Header.Add("Range" ,fmt.Sprintf("bytes=%d-%d",min,max))
res , e := http.DefaultClient.Do(req)
if e != nil{
return body , e
}
log.Printf("Index:%d . Range:bytes=%d-%d",i,min,max)
data , e :=ioutil.ReadAll(res.Body)
res.Body.Close()
if e != nil{
return body,e
}
log.Println("Data for request: ",len(data))
read = read + len(data)
body = append(body, data...)
}
log.Println("File size:",bodySize , "Downloaded size:",len(body)," Actual read:",read)
return body, nil
}
我还注意到,我设置的限制越大,原始文件内容长度与所有请求正文组合的实际大小之间的差异就越大。
这是我的main.go
func main() {
imgUrl := "https://media.wired.com/photos/5a593a7ff11e325008172bc2/16:9/w_2400,h_1350,c_limit/pulsar-831502910.jpg"
maxConnections := 4
manager := lib.NewManager(maxConnections)
data , e:= manager.DownloadBody(imgUrl)
if e!= nil{
log.Fatalln(e)
}
ioutil.WriteFile("foo.jpg" , data,0777)
}
注意:目前我对让代码并发不感兴趣。
有什么我可能会遗漏的想法吗?
注意:我已经确认服务器使用下面的 curl 命令返回了 206 部分内容:
curl -I https://media.wired.com/photos/5a593a7ff11e325008172bc2/16:9/w_2400,h_1350,c_limit/pulsar-831502910.jpg
【问题讨论】:
-
检查服务器是否实际返回带有
Content-Range标头的 206 响应,而不是普通的 200。服务器不需要接受范围请求。 -
Server Indeed 返回 206
-
在你的情况下,与其给你解决方案,不如邀请你写一个测试。请参阅这篇文章以了解如何在 go stackoverflow.com/questions/36540610/… 中提供范围请求,另请参阅 golang.org/pkg/net/http/httptest 如果您难以编写测试,它可能看起来像这样 play.golang.org/p/SoMew01qsFo
-
@mh-cbon 感谢您提供这些链接。明天有空的时候我会试着多读一些
标签: http go range-requests