0

0

C# HTTP范围请求下载 C#如何实现多线程分块下载(Range requests)

畫卷琴夢

畫卷琴夢

发布时间:2026-02-20 08:59:30

|

190人浏览过

|

来源于php中文网

原创

分块下载需手动构造带range头的httprequestmessage,严格格式为"bytes=start-end",服务器须支持accept-ranges;分块大小建议1–4mb并考虑存储对齐;须用semaphoreslim限并发、复用httpclient;写入文件必须按偏移定位而非完成顺序。

c# http范围请求下载 c#如何实现多线程分块下载(range requests)

Range 请求必须手动设置 Range 头,HttpClient 默认不发

HttpClient 不会自动拆分请求或加 Range 头——哪怕你传了 HttpCompletionOption.ResponseHeadersRead。它只管发完整 GET,服务器返回 200 就完事。要实现分块下载,你得自己构造多个独立的 HttpRequestMessage,每个都显式设置 Range 头,比如 "bytes=0-1048575"

常见错误是误以为用 WebClientHttpClient.SendAsync 加个参数就能“启用范围下载”,结果抓包一看全是 200,压根没触发 206 Partial Content。

  • 必须用 HttpRequestMessage + client.SendAsync() 手动发请求
  • Range 值格式严格:"bytes={start}-{end}",不能多空格、不能缺单位、不能写成 "0~1024"
  • 服务器必须支持(响应头含 Accept-Ranges: bytes),否则返回 416 或 200 全量内容

分块大小不是越大越好,1–4MB 是多数场景的平衡点

单块太大(如 64MB),内存占用高、失败重试成本大、网络抖动时容易超时;太小(如 64KB),HTTP 头开销占比飙升,线程/连接调度压力大,实际吞吐反而下降。实测在千兆局域网和普通云对象存储上,2MB 分块通常比 512KB 快 15–30%,又比 8MB 更稳。

注意:分块大小需对齐文件系统或存储服务的最小读单元(如某些 CDN 要求 512KB 对齐),否则可能触发额外 IO 或降速。

NexChatGPT
NexChatGPT

火爆全网的IDEA插件,支持IDEA全家桶

下载
  • 起始偏移必须是整数,end 可等于文件总长减 1(最后一块)
  • 避免让块边界落在压缩流或加密块中间(如 ZIP 内部结构、AES-CBC 段),否则解压/解密失败
  • FileInfo.Length 获取总大小前,先确认服务器返回了 Content-Length 或通过 HEAD 请求预取

并发控制别硬写 Task.WhenAll,用 SemaphoreSlim 限流更可靠

直接扔几十个 Task.Run(() => DownloadChunk(...))Task.WhenAll,极易打爆连接池、触发服务器限流(429)、或耗尽本地端口(SocketException: Only one usage of each socket address...)。.NET 的 HttpClient 连接池默认只允许 2–6 个并发连接(取决于 .NET 版本和配置)。

正确做法是用 SemaphoreSlim 控制同时进行的请求数(建议 4–8),并复用同一个 HttpClient 实例。

  • 不要为每个分块 new 一个 HttpClient,会泄漏连接
  • SemaphoreSlim.WaitAsync() 放在发送请求前,不是在回调里
  • 记得 await SemaphoreSlim.Release(),即使下载失败也要释放
  • 超时统一设在 HttpRequestMessage.Properties["StartTime"] 或用 CancellationTokenSource 管理

合并文件时顺序错乱是高频坑,别依赖 Task 完成顺序

分块下载完成后,各 Task 返回顺序完全不确定。如果按完成先后往文件里 Write,最终文件就是乱的——开头可能是第 5 块,中间夹着第 1 块。必须按逻辑偏移位置写入,而不是按执行顺序。

最简方案:每个分块下载完,把 byte[] 和对应 startOffset 存进线程安全集合(如 ConcurrentDictionary<long byte></long>),全部完成后遍历 offset 升序合并;更省内存的做法是打开 FileStream 并用 fileStream.Position = startOffset 定位写入。

  • 写入前检查 FileStream.CanSeek == true,某些流(如 NetworkStream)不支持
  • fileStream.Write(byteArray, 0, byteArray.Length),别用 WriteAsync 配合 Position——异步写入时 Position 可能被其他线程改
  • 最后一块长度可能小于分块大小,以响应头 Content-Range 中的 */{total} 为准,别信 byteArray.Length
分块下载真正的复杂点不在发请求,而在错误恢复:断点续传需要记录已成功写入的偏移,而部分失败的块重试时,得确保不会覆盖已写正确的内容。这个状态管理很容易被忽略,但一旦网络不稳定,就变成反复下载、反复覆盖、文件损坏。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

951

2023.09.19

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

951

2023.09.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

675

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

368

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

26

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

24

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

99

2026.02.06

CSS position定位有几种方式
CSS position定位有几种方式

有4种,分别是静态定位、相对定位、绝对定位和固定定位。更多关于CSS position定位有几种方式的内容,可以访问下面的文章。

83

2023.11.23

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

660

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.8万人学习

C 教程
C 教程

共75课时 | 4.8万人学习

C++教程
C++教程

共115课时 | 18.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号