我正在开发一个使用 .NET Web API 来下载文件的 Web 应用程序。对 API 的请求由使用 NSwag 生成的客户端代码处理。这一切在本地都运行良好,但是当使用 Azure 上托管的 API 时,客户端代码无法获取文件名。
客户端依赖“Content-Disposition”响应头来设置下载的文件名。该标头由 API 控制器自动添加,并返回 FileContentResult。但是,由于“Content-Disposition”不是 CORS 安全列表响应标头,客户端无法访问它,除非还提供“Access-Control-Expose-Headers”来允许它。
在 API 应用程序启动时的 CORS 策略中指定这一点在本地效果很好,但在 Azure 上托管时,似乎不遵守
WithExposedHeaders
设置。
在浏览器开发工具中查看“Content-Disposition”标头以及预期的文件名,但没有“Access-Control-Expose-Headers”。不过,使用本地 API 时,同一个请求具有预期的两个标头。
从 Azure 应用服务向我的客户端公开“Content-Disposition”标头的正确方法是什么?
以下是相关启动代码的简化版本:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.WithExposedHeaders("Content-Disposition");
});
});
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
以及 API 控制器的简化版本:
[HttpGet]
[Route("getfile")]
public async Task<ActionResult> GetFile(long id)
{
var file = await _fileService.GetFile(id);
return File(file.Content, file.MimeType, file.Name);
}
我认为问题可能在于 Azure 上定义的 CORS 设置覆盖了应用程序定义的策略,但清除所有 Azure CORS 设置没有效果。
我还尝试了这个答案中建议的设置,以“Content-Disposition”作为值,但它似乎没有做任何事情。不太确定这是否是一个有效的设置,因为除了那个答案之外我找不到任何其他参考。
似乎在 Azure 上设置公开的标头(如此处所示)应该是答案,但我的应用服务 CORS 配置没有这些选项。猜测这可能只适用于 Azure 容器应用程序。
可以考虑的一种方法是在 API 控制器操作中设置“Access-Control-Expose-Headers”标头。这样,无论 CORS 策略如何,您都可以检查响应中是否包含标头。
控制器.cs:
[HttpGet]
[Route("getfile")]
public async Task<ActionResult> GetFile(long id)
{
var file = await _fileService.GetFile(id);
// Add the "Access-Control-Expose-Headers" header
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
return File(file.Content, file.MimeType, file.Name);
}
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
公开响应中的“Content-Disposition”标头。这允许客户端访问标头并提取下载的文件名。这是公开默认 CORS 策略中未包含的标头的常用方法。我无法自己直接测试代码,不同托管环境中可能会出现意外的交互或限制。
额外的研究最终让我们找到了解决方案。简短回答:从作为 Azure 应用服务托管的 API 公开“Content-Disposition”标头的正确方法取决于如何通过 Azure 访问应用程序。