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

.NET Core 8文件下载:客户端无法获取Content-Disposition头

跨域场景下Blazor客户端无法获取Content-Disposition头的解决方案

原因分析

跨域请求中,浏览器默认仅允许客户端访问CORS明确暴露的响应头,Content-Disposition不在默认暴露的头列表内,因此即便服务端已设置该头,客户端也无法读取到。

解决方案

1. 服务端配置CORS,暴露Content-Disposition头

在ASP.NET Core的Program.cs中修改CORS策略,添加ExposeHeaders配置,明确允许客户端访问Content-Disposition头:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowBlazorClient", policy =>
    {
        policy.WithOrigins("https://localhost:7203") // 你的Blazor客户端地址
              .AllowAnyMethod()
              .AllowAnyHeader()
              .ExposeHeaders("Content-Disposition"); // 关键:暴露目标响应头
    });
});

// 确保CORS中间件在路由中间件之前启用
app.UseCors("AllowBlazorClient");

2. 优化服务端文件下载接口的头设置方式

直接使用ASP.NET Core框架提供的File()方法返回文件,框架会自动规范生成Content-Disposition头,避免手动设置可能出现的覆盖或编码问题:

[HttpGet("{fileName}")]
public async Task<IActionResult> Get(string fileName)
{
    try
    {
        if (string.IsNullOrWhiteSpace(fileName))
        {
            throw new ApplicationException("FileName is required as a path parameter.");
        }

        string fullPathName = Path.Combine(_settings.UploadRootFolder!, fileName);

        if (!System.IO.File.Exists(fullPathName))
        {
            throw new ApplicationException($"{fileName} does not exist in {_settings.UploadRootFolder}.");
        }

        var fileStream = new FileStream(fullPathName, FileMode.Open, FileAccess.Read);
        // 框架自动生成Content-Disposition头,包含正确的文件名编码
        return File(fileStream, MimeTypes.GetMimeType(fileName), fileName);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Exception trying to download a file");
        return BadRequest();
    }
}

3. 客户端读取Content-Disposition头的正确方式

修改Blazor客户端代码,现在可以正常读取响应头并处理文件名(注意去除可能存在的引号包裹):

private async Task btnDownload_Clicked(string fileName)
{
    if (!string.IsNullOrWhiteSpace(fileName))
    {
        try
        {                
            var response = await _apiClient.GetAsync($"/api/FileDownload/{fileName}");
            response.EnsureSuccessStatusCode();

            // 读取Content-Disposition头,优先取FileNameStar(支持UTF-8编码文件名)
            var contentDisposition = response.Content.Headers.ContentDisposition;
            var serverFileName = contentDisposition?.FileNameStar ?? contentDisposition?.FileName ?? fileName;
            
            // 去除文件名可能带有的双引号
            serverFileName = serverFileName?.Trim('"');

            using (var streamRef = new DotNetStreamReference(stream: await response.Content.ReadAsStreamAsync()))
            {
                await JS.InvokeVoidAsync("downloadFileFromStream", serverFileName, streamRef);
            }
        }
        catch (Exception ex)
        {
            await JS.InvokeVoidAsync("alert", ex.Message);
            throw;
        }
    }
}

验证步骤

  1. 重启服务端与客户端
  2. 发起下载请求,调试客户端代码确认response.Content.Headers.ContentDisposition不再为null
  3. 检查下载的文件名是否符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:27:24