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

ASP.NET Core 3.1 IIS托管下大于300MB文件下载返回0KB问题

问题修复方案

这个问题是代码生命周期错误+IIS托管环境默认大小限制/缓冲策略共同导致的,本地IIS Express默认缓冲阈值更高、调试环境不会主动回收未执行完的流资源,才会出现环境差异。

1. 修复代码逻辑错误

你当前代码存在两个会直接导致大文件返回空的问题:

  • 把HttpClient放在using块中声明:方法返回FileStreamResult时会立刻释放HttpClient实例,此时从SharePoint拉取的响应流还没完全写入客户端响应,大文件传输会被直接中断。小文件能正常下载是因为体积小,在流释放前已经全部载入内存缓冲。
  • 调用GetToken()时用了.Result同步阻塞:ASP.NET Core上下文里同步阻塞异步方法会造成线程池死锁,大文件传输耗时更长,触发死锁的概率远高于小文件。
  • 不要每次请求新建HttpClient实例,会造成端口耗尽问题,建议用IHttpClientFactory复用实例。

修正后的代码如下:

// 先在Startup.ConfigureServices中注册HttpClient:services.AddHttpClient();
public async Task<FileStreamResult> DownloadFile(string serverFileUrl, string fileName, [FromServices] IHttpClientFactory httpClientFactory)
{
    var accToken = await GetToken();
    var webUrl = "https://你的SharePoint站点根地址";
    var accessToken = accToken.ToString();

    var client = httpClientFactory.CreateClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    var requestUrl = $"{webUrl}/_api/web/getfilebyserverrelativeurl('{serverFileUrl}')/$value";
    var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead);
    response.EnsureSuccessStatusCode();
    var fileContent = await response.Content.ReadAsStreamAsync();

    // 不需要手动Dispose客户端和流,FileResult执行完成后会自动释放响应流,HttpClient由工厂统一管理生命周期
    return File(fileContent, System.Net.Mime.MediaTypeNames.Application.Octet, fileName, enableRangeProcessing: true);
}

2. 补全IIS和框架大小限制配置

300MB正好是IIS、ASP.NET Core默认的大小阈值临界点,需要同步修改两处配置:

2.1 修改web.config配置

在项目发布后的web.config中添加如下配置,示例配置支持最大2GB文件传输,可根据需求调整数值:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <!-- 配置IIS允许的最大请求长度,单位为字节,2147483648对应2GB -->
        <requestLimits maxAllowedContentLength="2147483648" />
      </requestFiltering>
    </security>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments="你的应用入口dll名称.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
      <handlerSettings>
        <!-- 关闭IIS层的响应缓冲,不要等大文件全部加载到内存再返回,直接流式传输 -->
        <handlerSetting name="bufferResponse" value="false" />
      </handlerSettings>
    </aspNetCore>
  </system.webServer>
</configuration>

2.2 配置服务端框架限制

在Startup.ConfigureServices中添加配置,取消Kestrel和MVC层的大小限制:

services.Configure<KestrelServerOptions>(options =>
{
    options.Limits.MaxRequestBodySize = null; // 不限制请求体大小
    options.Limits.MaxResponseBufferSize = null; // 关闭Kestrel层响应缓冲
});
services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = long.MaxValue; // 调整表单长度限制
});

如果需要针对单个接口放宽限制,可以在下载接口方法上添加特性:[RequestSizeLimit(long.MaxValue)]

3. IIS站点额外检查项

  • 打开对应IIS站点的「输出缓存」设置,关闭下载路径的缓存规则,避免大文件被缓存策略截断
  • 检查站点对应应用程序池的高级设置,将「启用32位应用程序」设为False,32位进程内存上限不足会导致大文件流处理中断
  • 确认应用程序池标识对站点目录、系统临时目录有读写权限,流式传输过程中需要临时目录存储分片数据

内容的提问来源于stack exchange,提问作者Anel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:30:43