You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用IIS Admin API+Refit分片编辑大文件遇HttpRequestException问题

IIS Admin API 分片编辑大文件时第二次请求失败的解决方法

我需要通过IIS Admin API编辑50MB的大文件,但API限制无法编辑超过30MB的文件,所以用分片+Refit库调用的方式处理。第一次分片请求成功,但第二次触发了HttpRequestException,问题出在这几个地方:

核心问题点

  1. Stream未截取分片,始终发送完整文件
    每次调用都传入了整个content流,但没有移动指针或截取对应片段,导致第二次请求的内容和Content-Range声明的范围不匹配,API直接报错。
  2. 循环条件错误,遗漏最后一块数据
    i < totalSize / 1000的判断会漏掉总大小不是1000倍数时的最后一块数据(比如50001字节,totalSize/1000等于50,循环到i=49就停止,漏掉第50块)。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:20:38