我正在与 Accept-Ranges 和 Goroutines 并行下载一个大的 .zip 文件。该应用程序使用其 Range 标头发送多个请求,以从 URL 下载 10MB 的 zip 文件块。请求被分成不同的范围作为单独的 Goroutines,并将获得的数据写入临时文件。这些文件被命名为 1、2、3....package mainimport ( "bufio" "fmt" "io" "io/ioutil" "log" "net/http" "os" "strconv" "sync")var wg sync.WaitGroupfunc main() { url := "https://path/to/large/zip/file/zipfile.zip" res, _ := http.Head(url) maps := res.Header length, _ := strconv.Atoi(maps["Content-Length"][0]) // Get the content length from the header request chunks := (length / (1024 * 1024 * 10)) + 1 // startByte and endByte determines the positions of the chunk that should be downloaded var startByte = 0 var endByte = (1024 * 1024 * 10) - 1 //body := make([][]byte, chunks) body := make([]io.ReadCloser, chunks) for i := 0; i < chunks; i++ { wg.Add(1) go func(min int, max int, i int) { client := &http.Client {} req, _ := http.NewRequest("GET", url, nil) rangeHeader := "bytes=" + strconv.Itoa(min) +"-" + strconv.Itoa(max) fmt.Println(rangeHeader) req.Header.Add("Range", rangeHeader) resp,_ := client.Do(req) defer resp.Body.Close() reader, _ := ioutil.ReadAll(resp.Body) body[i] = resp.Body ioutil.WriteFile(strconv.Itoa(i), reader, 777) // Write to the file i as a byte array wg.Done() }(startByte, endByte, i) startByte = endByte + 1 endByte += 1024 * 1024 * 10 } wg.Wait() filepath := "zipfile.zip" // Create the file _, err := os.Create(filepath) if err != nil { return } file, _ := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { log.Fatal(err) }下载完所有文件后,我尝试将它们重新组合成一个 .zip 文件。但是,当文件放在一起时,我无法解压缩最终文件,因为它似乎已损坏。我想知道我做错了什么,或者是否有更好的方法。提前致谢。
1 回答
紫衣仙女
TA贡献1839条经验 获得超15个赞
问题在于您的范围请求
线条
resp,_ := client.Do(req)
defer resp.Body.Close()
go vet由于未检查错误而被报告。如果您检查最后一个块中的响应代码是 416 - 这是使用的不正确范围,请更改为
resp, err := client.Do(req)
if err != nil {
panic(err)
}
if resp.StatusCode == 416 {
fmt.Println("incorrect range")
}
defer resp.Body.Close()
我还将循环变量更改为for i := 0; i < chunks-1; i++ { 并更改了 go 例程之后的部分
startByte = endByte + 1
endByte += 1024 * 1024 * 10
if startByte >= length {
break
}
for endByte >= length {
endByte = endByte - 1
}
并以类似的方式改变 j 循环变量
这些更改似乎对我有用,但我没有合适的测试数据来真正检查
- 1 回答
- 0 关注
- 103 浏览
添加回答
举报
0/150
提交
取消