如何在作为 Azure 应用服务托管的 ASP.NET Web API 上公开“Content-Disposition”响应标头?

问题描述 投票:0回答:2

我正在开发一个使用 .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 容器应用程序。

asp.net-mvc azure azure-web-app-service filecontentresult
2个回答
1
投票

可以考虑的一种方法是在 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 策略中未包含的标头的常用方法。我无法自己直接测试代码,不同托管环境中可能会出现意外的交互或限制。


0
投票

额外的研究最终让我们找到了解决方案。简短回答:从作为 Azure 应用服务托管的 API 公开“Content-Disposition”标头的正确方法取决于如何通过 Azure 访问应用程序。

  • 如果仅使用应用程序服务进行托管,则正确的方法似乎是在应用程序代码(例如 Startup.cs)中定义 CORS 策略,并在应用程序服务中禁用 CORS 功能。由于某种原因,应用服务似乎不提供配置此功能的功能,并且在那里启用 CORS 会覆盖应用程序代码中定义的任何内容。
  • 如果使用 Azure API 管理(就像我们的情况一样),必须将 CORS 配置为 API 管理中的策略(请参阅文档此处此处)。这似乎会覆盖其他地方设置的 CORS 策略,这就是为什么我们最初没有运气尝试在应用程序代码中设置它。
  • 如果通过其他层(如 Azure 应用程序网关)访问应用程序,则可能需要在那里配置标头。
© www.soinside.com 2019 - 2024. All rights reserved.