如何使用Golang实现文件下载加速_使用并发协程分片下载

Go 并发分片下载需先 HEAD 获取总大小并划分 [start,end] 字节区间,再并发 Range 请求写入临时文件,最后按序合并并校验 SHA256;支持断点续传、限速及错误重试。

使用 Go 语言实现并发分片下载,核心是将一个大文件按字节范围拆分成多个片段,每个片段由独立 goroutine 发起 HTTP Range 请求并写入对应临时位置,最后合并。关键在于正确处理 HTTP 头、字节偏移、并发控制和错误恢复。

1. 获取文件总大小并计算分片区间

先发起一次 HEAD 请求,从 Content-Length 响应头获取文件总长度。再根据预设线程数(如 4)或单片大小(如 2MB),划分出若干 [start, end] 字节区间。注意:end 是包含的,HTTP Range 使用 bytes=start-end 格式,且 end 最大为 total-1。

  • http.Head(url) 获取 size,超时需重试
  • 避免最后一片超出边界:end = min(start + pieceSize - 1, total-1)
  • 每片独立记录 offset 和长度,便于后续校验与续传

2. 并发发起 Range 请求并写入临时文件

为每个分片启动 goroutine,构造带 Range: bytes=start-end 的 GET 请求,响应体流式写入对应临时文件(如 file.part.001)。务必设置连接超时和读写超时,防止卡死。

  • io.CopyN(dst, resp.Body, int64(end-start+1)) 确保只写入目标字节数
  • 写入前创建空文件并 f.Seek(start, 0) 定位,支持随机写入
  • 用带缓冲的 bufio.Writer 提升小块写入性能

3. 合并分片并校验完整性

所有 goroutine 完成后,按序打开各 .part 文件,顺序读取并追加写入最终目标文件。合并完成后建议计算整体 SHA256 或 MD5,与服务端提供的摘要比对。

  • 合并时用 os.OpenFile(..., os.O_WRONLY|os.O_CREATE|os.O_TRUNC) 创建目标文件
  • 每个 part 文件用 io.Copy(dst, src) 流式拼接,不全加载进内存
  • 校验失败可只重下损坏的分片,无需全部重来

4. 支持断点续传与并发控制

下载前检查已有 .part 文件,跳过已完整写入的分片;用 semaphore 或带缓冲 channel 限制最大并发请求数(如 5),避免被服务端限流或本地 fd 耗尽。

  • 记录每个分片完成状态到 JSON 文件(如 file.meta),含 offset、size、md5
  • 使用 sync.WaitGroup 等待全部 goroutine 结束
  • 网络错误时记录失败区间,支持后续单独重试