乐闻世界logo
搜索文章和话题

Axios 如何实现文件下载?

9 个月前提问
5 个月前修改
浏览次数80

6个答案

1
2
3
4
5
6

当使用 Axios 进行文件下载时,我们需要设置适当的响应类型,并处理返回的数据以实现下载。这里是一个将 Axios 用于文件下载的步骤说明:

  1. 设置 Axios 请求以获取 Blob 数据: 要下载文件,我们需要以 blob 类型接收数据。在发送请求时,可以设置 Axios 的 responseType'blob'

  2. 发送 GET 请求: 发送到文件所在位置的 GET 请求将获取文件内容。

  3. 处理响应并创建下载链接: 一旦收到响应,我们将使用 URL.createObjectURL() 方法来创建一个指向该 blob 的 URL。

  4. 触发文件下载: 创建一个 a 标签,并设置 href 为之前创建的 blob URL,并设置 download 属性以指定下载文件的名称。然后通过编程方式触发 click 事件来开始下载。

  5. 清理: 下载完成后,应清理对象URL以释放浏览器中的资源。

下面是一个具体的代码示例:

javascript
import axios from 'axios'; function downloadFile(url, filename) { axios({ url: url, // 文件的 URL method: 'GET', responseType: 'blob', // 重要 }).then((response) => { // 创建一个链接元素 const link = document.createElement('a'); // 创建下载的链接 link.href = window.URL.createObjectURL(new Blob([response.data])); // 设置下载后文件的名称 link.setAttribute('download', filename); // 隐藏该元素 link.style.visibility = 'hidden'; // 将链接元素添加到DOM中 document.body.appendChild(link); // 触发点击 link.click(); // 移除链接元素 document.body.removeChild(link); // 清理URL对象 window.URL.revokeObjectURL(link.href); }).catch((error) => console.error('File download failed:', error)); } // 调用函数以下载文件 downloadFile('https://example.com/somefile.pdf', 'myFile.pdf');

在这个例子中,downloadFile 函数接受文件的 URL 和希望保存的文件名作为参数。然后,使用 Axios 发送 GET 请求并设置 responseTypeblob。一旦收到响应,我们创建一个不可见的 a 标签来触发下载。最后,确保在完成后清理已创建的 blob URL。

2024年6月29日 12:07 回复
  1. 使用 axios 下载文件作为responseType: 'blob'

  2. 使用 Axios/Server 响应中的 blob 创建文件链接

  3. 创建<a>HTML 元素,其中的 href 链接到步骤 2 中创建的文件链接并单击该链接

  4. 清理动态创建的文件链接和 HTML 元素

    axios({ url: 'http://api.dev/file-download', //your url method: 'GET', responseType: 'blob', // important }).then((response) => { // create file link in browser's memory const href = URL.createObjectURL(response.data);

    shell
    // create "a" HTML element with href to file & click const link = document.createElement('a'); link.href = href; link.setAttribute('download', 'file.pdf'); //or any other extension document.body.appendChild(link); link.click(); // clean up "a" element & remove ObjectURL document.body.removeChild(link); URL.revokeObjectURL(href);

    });

查看怪癖https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

完整学分:https: //gist.github.com/javilobo8

MDN 上提供了更多文档URL.createObjectURLURL.revokeObjectURL释放对象对于防止内存泄漏至关重要。在上面的函数中,由于我们已经下载了文件,因此我们可以立即撤销该对象。

每次调用 createObjectURL() 时,都会创建一个新的对象 URL,即使您已经为同一对象创建了一个 URL。当您不再需要它们时,必须通过调用 URL.revokeObjectURL() 来释放它们中的每一个。

当文档被卸载时,浏览器会自动释放对象URL;但是,为了获得最佳性能和内存使用率,如果存在可以显式卸载它们的安全时间,则应该这样做。

2024年6月29日 12:07 回复

当响应带有可下载文件时,响应标头将类似于

shell
Content-Disposition: "attachment;filename=report.xls" Content-Type: "application/octet-stream" // or Content-type: "application/vnd.ms-excel"

您可以做的是创建一个单独的组件,其中将包含一个隐藏的 iframe。

shell
import * as React from 'react'; var MyIframe = React.createClass({ render: function() { return ( <div style={{display: 'none'}}> <iframe src={this.props.iframeSrc} /> </div> ); } });

现在,您可以将可下载文件的 url 作为 prop 传递给该组件,因此当该组件收到 prop 时,它将重新渲染并下载文件。

**编辑:**您还可以使用js-file-download模块。链接到 Github 存储库

shell
const FileDownload = require('js-file-download'); Axios({ url: 'http://localhost/downloadFile', method: 'GET', responseType: 'blob', // Important }).then((response) => { FileDownload(response.data, 'report.csv'); });
2024年6月29日 12:07 回复

下载文件(使用 Axios 和 Security)

当您想要使用 Axios 和某些安全手段下载文件时,这实际上更加复杂。为了防止其他人花太多时间来解决这个问题,让我引导您完成这个过程。

你需要做三件事:

  1. 配置您的服务器以允许浏览器查看所需的 HTTP 标头
  2. 实现服务器端服务,并使其通告下载文件的正确文件类型。
  3. 实现 Axios 处理程序以在浏览器中触发 FileDownload 对话框

这些步骤大多是可行的 - 但由于浏览器与 CORS 的关系而变得相当复杂。一步一步来:

1. 配置您的 (HTTP) 服务器

当采用传输安全性时,浏览器中执行的 JavaScript [根据设计]只能访问 HTTP 服务器实际发送的 6 个 HTTP 标头。如果我们希望服务器建议下载的文件名,我们必须通知浏览器“可以”授予 JavaScript 访问将传输建议文件名的其他标头的权限。

为了便于讨论,我们假设我们希望服务器在名为X-Suggested-Filename 的HTTP 标头中传输建议的文件名。HTTP 服务器告诉浏览器可以_将_收到的自定义标头公开给 JavaScript/Axios,其中标头如下:

shell
Access-Control-Expose-Headers: X-Suggested-Filename

配置 HTTP 服务器以设置此标头的确切方法因产品而异。

有关这些标准标头的完整说明和详细说明,请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers 。

2. 实现服务器端服务

您的服务器端服务实现现在必须执行两件事:

  1. 创建(二进制)文档并将正确的 ContentType 分配给响应
  2. 分配包含客户端建议文件名的自定义标头 (X-Suggested-Filename)

根据您选择的技术堆栈,可以通过不同的方式完成此操作。我将使用 JavaEE 7 标准绘制一个示例,该示例应生成 Excel 报告:

shell
@GET @Path("/report/excel") @Produces("application/vnd.ms-excel") public Response getAllergyAndPreferencesReport() { // Create the document which should be downloaded final byte[] theDocumentData = .... // Define a suggested filename final String filename = ... // Create the JAXRS response // Don't forget to include the filename in 2 HTTP headers: // // a) The standard 'Content-Disposition' one, and // b) The custom 'X-Suggested-Filename' // final Response.ResponseBuilder builder = Response.ok( theDocumentData, "application/vnd.ms-excel") .header("X-Suggested-Filename", fileName); builder.header("Content-Disposition", "attachment; filename=" + fileName); // All Done. return builder.build(); }

该服务现在发出二进制文档(在本例中为 Excel 报告),设置正确的内容类型 - 并且还发送一个自定义 HTTP 标头,其中包含保存文档时要使用的建议文件名。

3. 为接收到的文档实现 Axios 处理程序

这里有一些陷阱,所以让我们确保所有细节都正确配置:

  1. 服务响应@GET(即HTTP GET),因此axios调用必须是'axios.get(...)'。
  2. 该文档作为字节流传输,因此您必须告诉 Axios 将响应视为 HTML5 Blob。(即_responseType: 'blob'_)。
  3. 在本例中,文件保护程序 JavaScript 库用于弹出浏览器对话框。但是,您可以选择另一个。

Axios 的框架实现将类似于:

shell
// Fetch the dynamically generated excel document from the server. axios.get(resource, {responseType: 'blob'}).then((response) => { // Log somewhat to show that the browser actually exposes the custom HTTP header const fileNameHeader = "x-suggested-filename"; const suggestedFileName = response.headers[fileNameHeader]; const effectiveFileName = (suggestedFileName === undefined ? "allergierOchPreferenser.xls" : suggestedFileName); console.log(`Received header [${fileNameHeader}]: ${suggestedFileName}, effective fileName: ${effectiveFileName}`); // Let the user save the file. FileSaver.saveAs(response.data, effectiveFileName); }).catch((response) => { console.error("Could not Download the Excel report from the backend.", response); });
2024年6月29日 12:07 回复

axios.post 与 IE 等浏览器的解决方案

我在这里找到了一些令人难以置信的解决方案。但他们常常不考虑 IE 浏览器的问题。也许这会为其他人节省一些时间。

shell
axios.post("/yourUrl", data, { responseType: 'blob' } ).then(function (response) { let fileName = response.headers["content-disposition"].split("filename=")[1]; if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE variant window.navigator.msSaveOrOpenBlob(new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' } ), fileName ); } else { const url = window.URL.createObjectURL(new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })); const link = document.createElement('a'); link.href = url; link.setAttribute('download', response.headers["content-disposition"].split("filename=")[1]); document.body.appendChild(link); link.click(); } } );

上面的示例适用于 Excel 文件,但只需稍作更改即可应用于任何格式。

在服务器上我这样做是为了发送 Excel 文件。

shell
response.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exceptions.xlsx")
2024年6月29日 12:07 回复

使用 axios 进行 API 调用的函数:

shell
function getFileToDownload (apiUrl) { return axios.get(apiUrl, { responseType: 'arraybuffer', headers: { 'Content-Type': 'application/json' } }) }

调用该函数,然后下载得到的 excel 文件:

shell
getFileToDownload('putApiUrlHere') .then (response => { const type = response.headers['content-type'] const blob = new Blob([response.data], { type: type, encoding: 'UTF-8' }) const link = document.createElement('a') link.href = window.URL.createObjectURL(blob) link.download = 'file.xlsx' link.click() })
2024年6月29日 12:07 回复

你的答案