C产品如何满足特定用户需求?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1149个文字,预计阅读时间需要5分钟。
断点下载失败最常见的原因是服务器返回了+302重定向,导致请求被自动跳转。这通常是由于HttpWebRequest默认开启了自动跳转功能(AllowAutoRedirect=true)。为了避免这个问题,需要将AllowAutoRedirect设置为false,自行处理重定向逻辑。
另一个隐蔽问题是连接复用:KeepAlive = false 会导致每次请求新建 TCP 连接,部分 CDN 或反向代理(如 Nginx)在非 Keep-Alive 下会忽略 Range 或直接返回 200。务必保持 KeepAlive = true(默认值,但显式写出更稳妥)。
- 手动处理重定向:收到 302 后,提取
Location响应头,用新 URL 构造请求,并重新设置Range - 禁用自动跳转后,需检查响应状态码:
response.StatusCode == HttpStatusCode.PartialContent才表示断点成功;若为OK,说明服务器不支持断点或 Range 被忽略 - 某些老旧 IIS 站点要求
UserAgent非空,否则拒收Range,可设一个常见 UA 字符串
如何正确计算并设置 Range 值?注意字节偏移和文件续写
Range 头格式是 "bytes={start}-{end}",其中 start 是已下载字节数(即本地文件当前长度),end 是本次请求截止位置(含)。如果文件已存在 1024 字节,想从第 1024 字节开始继续下载,且希望单次最多读 1MB,则 Range: bytes=1024-1048575(注意:1048575 = 1024 + 1024×1024 − 1)。
关键细节:
- 本地文件必须以
FileMode.Append或FileMode.Open+seek到末尾方式打开,不能用FileMode.Create覆盖 - 写入前调用
fileStream.Seek(0, SeekOrigin.End)确保写入位置准确;若用Append模式,.NET 会自动定位,但仍建议显式Seek校验 - 服务器可能返回比请求更小的 body(例如文件末尾不足 1MB),需以
response.ContentLength或实际读取字节数为准,而非预设大小
HttpWebResponse.ContentLength 为 -1?别信它,用 Headers["Content-Range"] 解析真实范围
当服务器返回 206 Partial Content 时,ContentLength 往往是 -1,因为响应体长度不等于整个文件长度。真正可靠的是 response.Headers["Content-Range"],其值形如 "bytes 1024-2047/1048576"。
必须解析这个头来确认本次下载是否完整、以及整个文件总大小:
- 用正则
bytes (\d+)-(\d+)/(\d+)提取三组数字;第三组是文件总长,用于初始化进度或校验 - 若第三组是
*(如bytes 1024-2047/*),说明服务器未提供总大小,只能靠后续响应或 HEAD 预请求获取 - 首次请求前建议先发一次
HEAD请求,读取Content-Length和Accept-Ranges响应头,确认服务端是否支持断点(Accept-Ranges: bytes是必要信号)
并发多段下载?小心 ServicePointManager.DefaultConnectionLimit
想提速而开多个 HttpWebRequest 并行下载不同 Range,结果发现最多只跑 2 个连接?这是 .NET Framework 默认限制所致。在 .NET Core/.NET 5+ 中该限制默认为 int.MaxValue,但旧版 Framework 默认仅 2。
解决方法很简单,但常被忽略:
- 全局设置:
ServicePointManager.DefaultConnectionLimit = 10;(建议在程序启动时执行一次) - 每个请求仍需独立设置
Range、AllowAutoRedirect = false、KeepAlive = true - 并发写入同一文件需加锁,推荐用
FileStream的FileShare.Write+ 显式Seek定位,避免用Append模式(多线程下不可靠) - 注意:不是所有 HTTP 服务器都允许高并发 Range 请求,Nginx 默认
limit_rate可能限速,IIS 有并发连接数限制
断点下载真正的难点不在发请求,而在状态同步和异常恢复:临时文件名、已下载区间记录、失败后从哪 resume —— 这些逻辑一旦漏掉,重试就变成重新下载。
本文共计1149个文字,预计阅读时间需要5分钟。
断点下载失败最常见的原因是服务器返回了+302重定向,导致请求被自动跳转。这通常是由于HttpWebRequest默认开启了自动跳转功能(AllowAutoRedirect=true)。为了避免这个问题,需要将AllowAutoRedirect设置为false,自行处理重定向逻辑。
另一个隐蔽问题是连接复用:KeepAlive = false 会导致每次请求新建 TCP 连接,部分 CDN 或反向代理(如 Nginx)在非 Keep-Alive 下会忽略 Range 或直接返回 200。务必保持 KeepAlive = true(默认值,但显式写出更稳妥)。
- 手动处理重定向:收到 302 后,提取
Location响应头,用新 URL 构造请求,并重新设置Range - 禁用自动跳转后,需检查响应状态码:
response.StatusCode == HttpStatusCode.PartialContent才表示断点成功;若为OK,说明服务器不支持断点或 Range 被忽略 - 某些老旧 IIS 站点要求
UserAgent非空,否则拒收Range,可设一个常见 UA 字符串
如何正确计算并设置 Range 值?注意字节偏移和文件续写
Range 头格式是 "bytes={start}-{end}",其中 start 是已下载字节数(即本地文件当前长度),end 是本次请求截止位置(含)。如果文件已存在 1024 字节,想从第 1024 字节开始继续下载,且希望单次最多读 1MB,则 Range: bytes=1024-1048575(注意:1048575 = 1024 + 1024×1024 − 1)。
关键细节:
- 本地文件必须以
FileMode.Append或FileMode.Open+seek到末尾方式打开,不能用FileMode.Create覆盖 - 写入前调用
fileStream.Seek(0, SeekOrigin.End)确保写入位置准确;若用Append模式,.NET 会自动定位,但仍建议显式Seek校验 - 服务器可能返回比请求更小的 body(例如文件末尾不足 1MB),需以
response.ContentLength或实际读取字节数为准,而非预设大小
HttpWebResponse.ContentLength 为 -1?别信它,用 Headers["Content-Range"] 解析真实范围
当服务器返回 206 Partial Content 时,ContentLength 往往是 -1,因为响应体长度不等于整个文件长度。真正可靠的是 response.Headers["Content-Range"],其值形如 "bytes 1024-2047/1048576"。
必须解析这个头来确认本次下载是否完整、以及整个文件总大小:
- 用正则
bytes (\d+)-(\d+)/(\d+)提取三组数字;第三组是文件总长,用于初始化进度或校验 - 若第三组是
*(如bytes 1024-2047/*),说明服务器未提供总大小,只能靠后续响应或 HEAD 预请求获取 - 首次请求前建议先发一次
HEAD请求,读取Content-Length和Accept-Ranges响应头,确认服务端是否支持断点(Accept-Ranges: bytes是必要信号)
并发多段下载?小心 ServicePointManager.DefaultConnectionLimit
想提速而开多个 HttpWebRequest 并行下载不同 Range,结果发现最多只跑 2 个连接?这是 .NET Framework 默认限制所致。在 .NET Core/.NET 5+ 中该限制默认为 int.MaxValue,但旧版 Framework 默认仅 2。
解决方法很简单,但常被忽略:
- 全局设置:
ServicePointManager.DefaultConnectionLimit = 10;(建议在程序启动时执行一次) - 每个请求仍需独立设置
Range、AllowAutoRedirect = false、KeepAlive = true - 并发写入同一文件需加锁,推荐用
FileStream的FileShare.Write+ 显式Seek定位,避免用Append模式(多线程下不可靠) - 注意:不是所有 HTTP 服务器都允许高并发 Range 请求,Nginx 默认
limit_rate可能限速,IIS 有并发连接数限制
断点下载真正的难点不在发请求,而在状态同步和异常恢复:临时文件名、已下载区间记录、失败后从哪 resume —— 这些逻辑一旦漏掉,重试就变成重新下载。

