断点续传的核心是“校验+分块+记录”,而非简单重传;需客户端分块、存进度、跳过已传块,服务端提供分片上传与合并校验接口,并保障幂等性与状态一致性。
断点续传的核心不是“重传”,而是“校验+分块+记录”
断点续传上传在 C# 中没有现成的
一键方法。它本质是客户端主动管理文件切片、服务端配合校验已传片段、双方通过唯一标识(如文件 hash 或分片编号)确认进度。强行用
或简单
直传整个文件,失败后只能从头再来——这不是断点续传,只是“重试”。
客户端必须自己分块并记录上传状态到本地
关键动作不在网络库,而在你如何切文件、存进度、跳过已传块。常见错误是把“上传失败后重新调用同一方法”当成续传,结果重复发了全部数据。
用
+
按固定大小(如 4MB)读取文件块,避免一次性加载大文件进内存
每块生成唯一标识:推荐
(不要只用
,防止不同文件冲突)
上传前先查本地状态文件(如
),读取已成功上传的
列表
只对未上传或校验失败的块发起请求;上传成功后立即追加写入该
到状态文件(建议用
+ 行式存储,避免并发写损坏)
服务端需提供两个最小接口:分片上传 + 合并校验
ASP.NET Core 中,别指望
能直接处理分片——它默认等待整个 multipart body 完整才触发绑定,超时或中断就全丢。必须手动解析 raw request body。
C知道
CSDN推出的一款AI技术问答工具
下载
:接收
,提取
、
、
和二进制块。保存路径建议为
:收到所有块后,按序拼接并计算最终文件 hash,与客户端传来的
对比;一致才写入正式目录,否则返回 400 并清空临时块
注意:上传块接口必须支持幂等(相同
多次提交应视为一次成功),避免网络重发导致块重复写入
HttpClient 不要复用默认实例做分块上传
用全局单例
发大量小块请求,容易触发连接池耗尽或 TIME_WAIT 爆满。尤其在 Windows 上,默认连接数限制低(如 .NET 6 默认 10),上传 100 块就卡住。
为每个文件上传新建一个
实例(配合
),或至少按上传任务隔离连接池:
给每个分块请求显式设置超时:
(不能依赖全局 Timeout)
禁用自动重定向:
,避免分块请求被中间代理误判
别用
包裹每个块——它会额外加 boundary 开销。直接用
+ 手动构造 header 更轻量
真正难的不是代码怎么写,而是状态一致性:客户端认为某块传完了,服务端因磁盘满没写入,但返回了 200;或者合并时发现少一块,却找不到是哪边丢了日志。务必在每一步加可追溯的 traceId,并让客户端和服务端都记录
、
、
、
四元组。
UploadWithResume()WebClientHttpClient.PostAsync()FileStreamBufferedStreamfileHash + chunkIndexchunkIndexupload_state.jsonchunkIndexchunkIndexFile.AppendAllText()IFormFilePOST /api/upload/chunkmultipart/form-datafile_hashchunk_indextotal_chunks./uploads/{file_hash}/{chunk_index}POST /api/upload/mergefile_hashfile_hash + chunk_indexHttpClientHttpClientusingnew SocketsHttpHandler { MaxConnectionsPerServer = 32 }client.Timeout = TimeSpan.FromMinutes(5)client.DefaultRequestHeaders.ExpectContinue = falseMultipartFormDataContentByteArrayContentfile_hashchunk_indexbytes_senthttp_status