用HttpClient分片下载需复用实例、设Range头为bytes=start-end、检查206状态码;响应流须FileStream偏移写入,禁用AppendAllBytes;多线程应每分片独用FileStream,避免竞态。

C#怎么实现文件分片下载_C#如何计算HTTP请求范围【源码】

怎么用 HttpClient 发起带 Range 头的分片请求

分片下载本质就是让服务器只返回文件某一段字节,关键在发请求时加 Range 请求头。C# 里最稳妥的方式是用 HttpClient 手动设置,而不是依赖 DownloadFileAsync 这类黑盒方法——它不支持断点续传或自定义范围。

实操要点:

示例片段:

client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(0, 1023);

如何安全读取 HttpContent 的原始字节并写入文件偏移位置

拿到响应后,不能直接 content.ReadAsStringAsync()ReadAsByteArrayAsync()——它们会把整个流缓存进内存,大文件直接 OOM。必须用流式读取 + FileStreamPositionWrite 偏移写入。

常见错误现象:

正确做法是:打开 FileStream 时用 FileMode.Open + FileAccess.Write,再调 fs.Position = startOffset,然后 await stream.CopyToAsync(fs)

怎么判断服务器是否真正支持分片(Accept-Ranges 不可靠)

Accept-Ranges: bytes 只是声明“可能支持”,不代表本次请求真能分片。很多 CDN 或 Nginx 配置漏掉 add_header Accept-Ranges bytes,或者对某些路径禁用了范围请求。

更可靠的验证方式是实际发一个试探请求:

注意:某些服务器(如 IIS 默认配置)对小范围(如 0-0)会静默转成 200,所以最好试 0-1023 并比对 Content-Range 头是否匹配。

多线程并发分片时,FileStream 写入为什么崩了

多个 Task 同时往同一个 FileStream 写,即使各自写不同 offset,也会因底层缓冲、Position 竞态、或 Windows 文件锁机制出错——典型报错是 System.IO.IOException: The process cannot access the file 或写入错位。

根本原因不是“没加锁”,而是 FileStream 本身不是线程安全的写入对象。解决方案只有两个:

额外提醒:别用 MemoryStream 缓冲全部分片再统一写——又回到内存爆炸的老路。

分片逻辑本身不难,难的是 HTTP 层的容错(比如 206 没返回却假装成功)、文件系统层的原子写(尤其断电/崩溃时部分分片已落盘)、以及多线程下磁盘 IO 的实际吞吐未必随线程数线性增长。这些地方不埋日志、不加重试、不验 MD5,上线后第一波并发就露馅。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。