需要从使用javascript fetch api下载的文件中获取文件名吗?

时间:2018-03-14 19:28:01

标签: javascript fetch-api

在我的javascript客户端中,我使用fetch来调用服务器来检索服务器生成的文件。我使用以下客户端代码:

var _url = "";    
var initParms = {  
   method: "GET",
   mode: 'cors'
}

fetch(_url, initParms)
.then(response => {
   if(response.ok){
      alert(response.headers.get("content-disposition"));
      return response.blob();
   }

   throw new Error("Network response was not OK.");
})
.then(blob => {
   var url = new URL.createObjectURL(blob);
})     

这实际上很好用。但是,服务器会为文件生成文件名,并将其作为content-disposition标头的一部分包含在响应中。

我需要使用服务器生成的文件名将此文件保存到用户的计算机。在Postman中,我实际上可以看到响应的内容处置标头设置为:Content-Disposition: attachment;filename=myfilename.txt

我尝试从响应中读取内容处理(请参阅我的js代码中的警告),但我总是得到null(即使相同的响应显示Postman中的内容处置)。

我做错了吗?有没有办法使用fetch响应检索文件名?有没有更好的方法从服务器获取文件名和文件?

P.S。这是我返回文件的服务器端代码:

控制器操作

public IHttpActionResult GetFile(){
   return new FileResult("myfilename.txt","Hello World!");
}

FileResult Class

public class FileResult : IHttpActionResult
{
   private string _fileText = "";
   private string _fileName = "";
   private string _contentType = "";

   public FileResult(string name, string text)
   {
       _fileText = text;
       _fileName = name;
       _contentType = "text/plain";
   }

   public Task<HttpResponseMessage> ExecuteActionAsync(CancellationToken token)
   {
        Stream _stream = null;
        if (_contentType == "text/plain")
        {
            var bytes = Encoding.Unicode.GetBytes(_fileText);
            _stream = new MemoryStream(bytes);
        }
        return Task.Run(() =>
        {
            var response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StreamContent(_stream),
            };

            response.Content.Headers.ContentType = 
                new MediaTypeHeaderValue(_contentType);
            response.Content.Headers.ContentDisposition = 
                new ContentDispositionHeaderValue("attachment")
            {
                FileName = _fileName
            };

            return response;

        }, token);

修改

我的问题是关于抓取而不是ajax api。此外,在我的代码中,我表明我已经从响应中读取标题,就像在建议的答案中显示的接受答案一样。但是,正如我的帖子所述,此解决方案不适用于fetch。

2 个答案:

答案 0 :(得分:1)

因此,在发布此问题后不久,我遇到了this issue on Github。它显然与使用CORS有关。

建议的解决方法是将Access-Control-Expose-Headers:Content-Disposition添加到服务器上的响应标头中。

这很有用!

答案 1 :(得分:1)

您可以像这样从 content-disposition 标头中提取文件名:

let filename = '';

fetch(`/url`, { headers: { Authorization: `Bearer ${token}` }}).then((res) => {
    const header = res.headers.get('Content-Disposition');
    const parts = header!.split(';');
    filename = parts[1].split('=')[1];
    return res.blob();
}).then((blob) => {
    // Use `filename` here e.g. with file-saver:
    // saveAs(blob, filename);
});