有效断点续传需手动设置range头为"bytes=n-",服务端必须返回206状态码及content-range头;先head校验accept-ranges支持,再用os.stat获取偏移量、seek定位写入,禁用o_append。

HTTP Range 请求头怎么发才有效
断点续传本质是客户端告诉服务端“我已下载到第 N 字节,从这里继续”,关键在 Range 请求头。Go 的 http.Request 不会自动加它,必须手动设置:
- 格式必须为
bytes=N-(末尾带短横),例如已下载 1024 字节,就发Range: bytes=1024- - 不能写成
bytes=1024-2047(除非你明确要下载片段),续传场景下后半段留空 - 服务端返回状态码必须是
206 Partial Content,不是200 OK;如果返回200,说明服务端没支持 Range,或请求头被忽略(常见于 Nginx 默认配置) - 用
curl -H "Range: bytes=1024-" -I http://example.com/file.zip先验证服务端是否响应206和Content-Range头
Go 客户端如何复用连接并追加写入文件
断点续传不是重新开文件写,而是以 os.O_WRONLY | os.O_CREATE | os.O_APPEND 模式打开,并用 file.Seek() 定位到已下载末尾。但注意:O_APPEND 会强制写入末尾,和 Seek 冲突,所以实际要用 os.O_WRONLY | os.O_CREATE,再手动 Seek:
- 先用
os.Stat()获取本地文件大小,作为起始偏移量offset - 打开文件时用
os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644),不要加O_APPEND - 调用
file.Seek(offset, io.SeekStart)移动写入位置,再开始读响应体写入 - 务必检查
http.Response.StatusCode是否为206,否则可能把整个文件重写进已存在文件的中间位置,导致损坏
服务端没返回 Content-Range 怎么办
Go 标准库 http.ServeContent 会自动处理 Range 请求并返回 Content-Range,但很多自定义 handler 或反向代理(如未配 add_header Accept-Ranges bytes; 的 Nginx)会丢掉这个头。此时客户端无法校验下载完整性:
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 若服务端不返回
Content-Range,response.Header.Get("Content-Range")为空,你只能靠Content-Length+ 已下载字节数推算,但不可靠(压缩、动态生成等场景失效) - 更稳妥的做法:首次请求先发 HEAD,检查是否有
Accept-Ranges: bytes响应头,没有就放弃断点续传逻辑,走全量下载 - 部分 CDN 或对象存储(如 AWS S3)需显式开启 Range 支持,S3 默认支持,但签名 URL 若过期或权限不足,也会降级为
200
并发下载多个分片时要注意什么
单纯用多个 Range 并发下载(如 0-1023、1024-2047)能提速,但 Go 实现时容易出错:
- 每个分片必须独立打开文件,用
file.Seek()定位,且写入前加锁(或用sync.WaitGroup+ 单 goroutine 写入),避免多 goroutine 同时Write导致覆盖 - 不要用
io.CopyN依赖Content-Length,因为分片响应的Content-Length是该段长度,不是全局长度;应按实际读取字节数累加 - 最后需校验总字节数是否等于
Content-Length(首次 HEAD 获取)或服务端提供的Content-Range中的总长度(如bytes 0-1023/1048576中的1048576) - HTTP/2 下并发请求复用连接没问题,但 HTTP/1.1 需确保服务端支持
Pipeline或启用多连接(http.Transport.MaxConnsPerHost调高)
最易被忽略的是:断点续传逻辑里没做服务端能力探测,就默认对方支持 Range;还有就是文件打开模式写错,导致续传时从头覆盖。这两个点一错,下载看起来“成功”了,文件却损坏。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










