使用IIS Admin API+Refit分片编辑大文件遇HttpRequestException问题
IIS Admin API 分片编辑大文件时第二次请求失败的解决方法
我需要通过IIS Admin API编辑50MB的大文件,但API限制无法编辑超过30MB的文件,所以用分片+Refit库调用的方式处理。第一次分片请求成功,但第二次触发了HttpRequestException,问题出在这几个地方:
核心问题点
- Stream未截取分片,始终发送完整文件
每次调用都传入了整个content流,但没有移动指针或截取对应片段,导致第二次请求的内容和Content-Range声明的范围不匹配,API直接报错。 - 循环条件错误,遗漏最后一块数据
i < totalSize / 1000的判断会漏掉总大小不是1000倍数时的最后一块数据(比如50001字节,totalSize/1000等于50,循环到i=49就停止,漏掉第50块)。 - Content-Range最后一块上限计算错误
当处理最后一块时,totalSize % 1000 -1会导致如果最后一块只有1字节时,上限变成-1,完全不符合HTTP规范。
修正后的代码
分片处理逻辑
var totalSize = content.Length; // 先确保流支持定位,不支持则转成MemoryStream if (!content.CanSeek) { var ms = new MemoryStream(); content.CopyTo(ms); ms.Position = 0; content = ms; } const int chunkSize = 1000; // 计算总分片数,向上取整避免遗漏 var totalChunks = (int)Math.Ceiling((double)totalSize / chunkSize); for (int i = 0; i < totalChunks; i++) { var lowerLimit = i * chunkSize; // 最后一块的上限取文件总大小-1,避免越界 var upperLimit = Math.Min((i + 1) * chunkSize - 1, totalSize - 1); var contentLength = upperLimit - lowerLimit + 1; // 定位流到当前分片起始位置 content.Position = lowerLimit; // 截取当前分片的流片段 var chunkStream = new MemoryStream(); content.CopyTo(chunkStream, contentLength); chunkStream.Position = 0; var headers = new Dictionary<string, string> { { "Content-Length", $"{contentLength}" }, { "Content-Range", $"bytes {lowerLimit}-{upperLimit}/{totalSize}" } }; await _client.EditFileUnderDirectoryInChunks(chunkStream, fileId, AccessTokenHeaderValue, headers, cancellationToken).ConfigureAwait(false); chunkStream.Dispose(); }
优化Refit客户端定义
可以把Content-Length和Content-Range拆成单独参数,避免用HeaderCollection,更直观且不易出错:
[Put("/api/files/content/{fileId}")] [Headers("Content-Type: application/octet-stream")] Task EditFileUnderDirectoryInChunks( [Body] Stream content, string fileId, [Header("Access-Token")] string accessToken, [Header("Content-Length")] long contentLength, [Header("Content-Range")] string contentRange, CancellationToken cancellationToken = default);
额外排查建议
- 查看
HttpRequestException的InnerException或具体错误状态码,确认是4xx(比如Range格式不合法)还是5xx错误,精准定位问题。 - 确保IIS Admin API的分片编辑支持标准的
Content-Range格式(bytes start-end/total)。
内容的提问来源于stack exchange,提问作者Atif
相关产品推荐
相关产品推荐

