【问题标题】:Fetch API to force download fileFetch API 强制下载文件
【发布时间】:2017-10-25 08:54:27
【问题描述】:

我正在调用一个 API 以使用 fetch API 从服务器下载 excel 文件,但它并没有强制浏览器下载,下面是我的标题响应:

HTTP/1.1 200 OK Content-Length: 168667 
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 
Server: Microsoft-IIS/8.5 
Content-Disposition: attachment; filename=test.xlsx 
Access-Control-Allow-Origin: http://localhost:9000 
Access-Control-Allow-Credentials: true 
Access-Control-Request-Method: POST,GET,PUT,DELETE,OPTIONS 
Access-Control-Allow-Headers: X-Requested-With,Accept,Content-Type,Origin 
Persistent-Auth: true 
X-Powered-By: ASP.NET 
Date: Wed, 24 May 2017 20:18:04 GMT

在我用来调用 API 的代码下方:

this.httpClient.fetch(url, {
    method: 'POST',
    body: JSON.stringify(object),
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
})

【问题讨论】:

  • 您可能想使用stackoverflow.com/posts/44168090/edit 更新/编辑您的问题,以添加您用于尝试下载文件的代码的 sn-p
  • 你是如何“调用 API”的?
  • this.httpClient.fetch(url, { method: 'POST', body: JSON.stringify(object), headers: { 'Accept': 'application/json', 'Content-Type' : '应用程序/json' } })
  • 我发现使用blob方法下载但是否有其他方法强制下载?
  • 作为一项安全功能 - JavaScript 无法使用 AJAX 开始下载到您的计算机 - 因为它无权将文件写入您的计算机。

标签: download aurelia fetch-api


【解决方案1】:

只有当您导航到该资源时,浏览器才会显示下载的常规交互(显示另存为...对话框等)。举个例子更容易说明区别:

  1. window.location='http://mycompany.com/'
  2. 通过 XHR/Fetch 在后台加载 http://mycompany.com/

在1.中,浏览器将加载页面显示其内容。 2.中,浏览器会加载原始数据并返回给你,但你必须自己显示。

你必须对文件做类似的事情。你有原始数据,但你必须自己“显示”它。为此,您需要为下载的文件创建一个对象 URL 并导航到它:

this.httpClient
    .fetch(url, {method, body, headers})
    .then(response => response.blob())
    .then(blob => URL.createObjectURL(blob))
    .then(url => {
        window.open(url, '_blank');
        URL.revokeObjectURL(url);
    });

这会获取响应,将其作为 blob 读取,创建 objectURL,将其打开(在新选项卡中),然后撤销 URL。

有关对象 URL 的更多信息: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL

【讨论】:

  • 此答案将打开一个新选项卡以预览图像。但是因为使用的是URL.revokeObjectURL(url);所以图片不能下载
【解决方案2】:

我找到了另一种下载方式,它可以在 IE 上使用

https://www.npmjs.com/package/downloadjs

【讨论】:

    【解决方案3】:

    有一些方便的库,为了解决我在下载 CSV/文本时遇到的问题,我使用了FileSaver

    例子:

    var saveAs = require('file-saver');
    
    fetch('/download/urf/file', {
      headers: {
        'Content-Type': 'text/csv'
      },
      responseType: 'blob'
    }).then(response => response.blob())
      .then(blob => saveAs(blob, 'test.csv'));
    

    还有download.js lib,如this question 中所述。

    【讨论】:

    • 如果您正在发出 GET 请求,为什么要设置请求标头“Content-Type: application/pdf”?
    • @sstur 请求标头对象具有保护属性。这不会暴露给 Web,但它会影响 headers 对象上允许的突变操作。发现于developer.mozilla.org/en-US/docs/Web/API/Fetch_API/…
    • 我仍然认为这不能解释为什么您要在没有正文的 GET 请求上设置 Content-Type。在这种情况下,Content-Type 的含义/目的是什么?
    【解决方案4】:

    你可以使用下面的函数来做到这一点

    download(filename) {
     fetch(url , { headers })
     .then(response => response.blob())
     .then(blob => URL.createObjectURL(blob))
     .then(uril => {
     var link = document.createElement("a");
     link.href = uril;
     link.download = filename + ".csv";
     document.body.appendChild(link);
     link.click();
     document.body.removeChild(link);
     });
    }
    

    这里我想下载一个 CSV 文件,所以我在文件名中添加了 .csv。

    【讨论】:

      【解决方案5】:

      我的解决方案基于@VINEE 和@balazska 解决方案。我想避免操纵document.body 或通过window.open(url, '_blank'); 打开一个新标签

      return fetch(urlEndpoint, options)
        .then((res) => res.blob())
        .then((blob) => URL.createObjectURL(blob))
        .then((href) => {
          Object.assign(document.createElement('a'), {
            href,
            download: 'filename.csv',
          }).click();
        });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-31
        • 1970-01-01
        • 2013-06-20
        • 2013-01-27
        • 1970-01-01
        相关资源
        最近更新 更多