从ASP.NET CORE Web Api中获取React特定的响应头(例如Content-Disposition)

5
我将从一个WebAPI控制器返回一个文件。自动填充了Content-Disposition头,并包含我的文件名。
我的后端代码如下:
[HttpGet("Download")]
public async Task<ActionResult> Download([FromQuery]CompanySearchObject req)
{
    string fileName = "SomeFileName_" + DateTime.UtcNow.Date.ToShortDateString() + ".csv";

    var result = await _myService.GetData(req);

    Stream stream = new System.IO.MemoryStream(result);

    return File(stream, "text/csv", fileName.ToString());
}

在我的前端:

exportData(params).then(response => {
      console.log(response);
      console.log('Response Headers:', response.headers);
      const type = response.headers['content-type'];
      const blob = new Blob([response.data], { type: type, encoding: 'UTF-8' });
      //const filename = response.headers['content-disposition'].split('"')[1];
      //alert(filename);
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = 'file.xlsx';
      link.click();
      link.remove();
   });
};

enter image description here

但是我正在努力获取这些数据,因为当我在前端上做console.log时,我看不到这个..正如您所看到的,我记录了响应 console.log('Response Headers:', response.headers);但是我只能看到:

enter image description here

这些数据不应该在某个地方吗?我想知道如何读取Content-Disposition中的值并获取文件名?

谢谢大家
干杯

5个回答

7

我遇到了同样的问题,我的问题是由于CORS导致的。如果您正在使用CORS,则需要在您的配置中像这样公开它:

app.UseCors(builder =>
            {
                builder.AllowAnyOrigin();
                builder.AllowAnyMethod();
                builder.AllowAnyHeader();
                builder.WithExposedHeaders("Content-Disposition"); // this is the important line
            });

2
对于获取响应头,它返回一个可迭代对象,你需要通过循环遍历 response.headers 而不是 log response.headers object
尝试以下代码:
response.headers.forEach(console.log);
console.log(response.headers.get('content-disposition'));

2
我通常通过循环遍历所有请求头,直到匹配到我要查找的特定头部来实现。最初的回答。
// Headers
private void GetSetCustomHeaders(ref string theUsername, ref string thePassword, ref string theAPIKey)
{
    try
    {
        foreach (KeyValuePair<string, IEnumerable<string>> header in this.Request.Headers)
        {
            string headerType = header.Key;
            string headerTypeUpperTrim = headerType.Trim().ToUpper();
            IEnumerable<string> headerValue = header.Value;
            string fullHeaderValue = "";
            bool isFirstHeaderValue = true;
            foreach (string headerValuePart in headerValue)
            {
                if (isFirstHeaderValue)
                {
                    fullHeaderValue = headerValuePart;
                    isFirstHeaderValue = false;
                }
                else
                {
                    fullHeaderValue = fullHeaderValue + Environment.NewLine + headerValuePart;
                }
            }
            if (headerTypeUpperTrim == "USERNAME")
            {
                theUsername = fullHeaderValue;
            }
            else if (headerTypeUpperTrim == "PASSWORD")
            {
                thePassword = fullHeaderValue;
            }
            else if (headerTypeUpperTrim == "APIKEY")
            {
                theAPIKey = fullHeaderValue;
            }
        }
    }
    catch (Exception)
    {
        //MessageBox.Show("Error at 'GetSetCustomHeaders'" + Environment.NewLine + Environment.NewLine + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

在上面的示例代码中,我正在寻找“用户名”、“密码”和“API密钥”。它们作为ref参数传递,因此如果在此方法中设置了它们,则在调用此GetSetCustomHeaders方法的方法中也设置了它们,因为它引用相同的内容。因此,当我最初调用此方法时,我的变量设置为string.Empty
希望这有所帮助。

0

这是正确的,我遇到了这个问题。试试看。

只能在服务器端(后端)解决。您必须添加后端响应头,如下所示:

Access-Control-Expose-Headers: [Content-Disposition, .....您可以添加多个标头]

之后,您可以直接使用 response.headers 访问此标头。


0
我找到了一个类似的解决方案,与@Kaca992提出的解决方案相似,但适用于Azure Functions(隔离而不是进程内)和每个函数方法。
    [Function(name: "FunctionMethod")]
    public async Task<HttpResponseData> FunctionMethod(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "my/route")] HttpRequestData req, FunctionContext context)
    {
        // await async work for get Request...
        // e.g. await getBlobFromService();

        // fyi: Get Content-Type from library with FilePath /w extension
        var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider();
        var success = provider.TryGetContentType("myfile.pdf", out string contentType); // Parse results in application/pdf.

        // Create response with Access-Control-Expose-Headers header and add Content-Disposition.       
        var okResponse = req.CreateResponse(statusCode: HttpStatusCode.OK);
        okResponse.Headers.Add("Content-Type", contentType); // Assumes a successful parse.
        okResponse.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
        okResponse.Headers.Add("Content-Disposition", "inline;filename=\"myFile.pdf\"");
        return okResponse;

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接