8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何使用 axios 下载文件

Austin Wolff 2月前

163 0

我正在使用 axios 进行基本的 http 请求,例如 GET 和 POST,效果很好。现在我也需要能够下载 Excel 文件。使用 axios 可以实现吗?如果可以,有人有示例代码吗?

我正在使用 axios 进行基本的 http 请求,例如 GET 和 POST,效果很好。现在我也需要能够下载 Excel 文件。使用 axios 可以实现这一点吗?如果可以,有人有示例代码吗?如果没有,我还可以在 React 应用程序中使用什么来做同样的事情?

帖子版权声明 1、本帖标题:如何使用 axios 下载文件
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Austin Wolff在本站《express》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 当响应带有可下载文件时,响应标头将类似于:

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

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

    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 repo

    const FileDownload = require('js-file-download');
    
    Axios({
      url: 'http://localhost/downloadFile',
      method: 'GET',
      responseType: 'blob', // Important
    }).then((response) => {
        FileDownload(response.data, 'report.csv');
    });
    
  • 是的,页面不会被阻止。当您将 url 作为 prop 传递给该组件时,文件将自动下载。您无需执行任何操作。

  • 还有一个问题。在我的情况下,正在下载的文件是动态创建的,并传递了一些参数。因此它实际上没有一致的位置。对于这种情况,我发送的 URL 是什么?例如,如果我调用 axios.post('api/getmyexcelfile', params);

  • 正如这个答案中提到的。在 axios 响应对象中,请求内部有一个名为 As responseURL 的字段,也许这就是您想要的 URL。

  • 我按照这个操作,可以下载文件。但文件已损坏(无法使用)。但是,如果我使用重定向(window.location.href),文件可以下载并正常运行。有人能帮我解决这个问题吗?(.com/questions/56306008/…)

    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);
    
        // 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

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

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

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

  • 感谢您的解决方案。仅供其他人参考:虽然这可能适用于很多用例,但对于大文件,您将无法看到下载进度。而且它会占用浏览器中的额外内存。正如其他解决方案中提到的,但没有说明的那样,一般方法是使用标头“Content-Disposition:附件;”,这样浏览器就会将其视为本机下载(前面提到的下载进度 + 直接下载到磁盘)。

  • 在服务器端,即使我设置了 Content-Desposition 标头,它似乎也不允许下载进度。

  • 谢谢。想知道为什么文件内容显示不正确。原来是我漏掉了 responseType: 'blob'

  • 我们需要 document.body.appendChild(link); 这一行吗?即使没有这一行,解决方案对我来说也是可行的(Chrome)

  • @Vinay 此解决方案有内存开销。无需 document.body.appendChild(link)。在 link.click() 之后还可以使用 window.URL.revokeObjectURL(url)

  • 下载文件(使用 Axios 和 Security)

    当您想使用 Axios 和一些安全手段下载文件时,这实际上会更加复杂。为了防止其他人花太多时间弄清楚这一点,让我带您了解一下。

    你需要做三件事:

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

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

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

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

    为了便于讨论,我们假设我们希望服务器在名为 X-Suggested-Filename 的 。HTTP 服务器告诉浏览器可以 使用 以下标头将接收到的自定义标头公开给 JavaScript/Axios:

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

    配置 HTTP 服务器来设置此标头的具体方法因产品而异。

    有关这些标准标头的完整解释和详细描述, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

    2.实现服务端服务

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

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

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

        @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 实现将类似于以下内容:

         // 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);
            });
    
  • 它是一个处理下载文件的库,github.com/eligrey/FileSaver.js/#filesaverjs

  • 这是可行的,但建议使用 content-disposition 标头而不是 x-suggested-filename。

  • 这很好,但它忽略了一个核心点,即在使用 blob 作为 responseType 执行 axios.get(resource, {responseType: 'blob'}).then((response) => () => {}) 时,即使服务器将数据作为块传输,整个文件也会加载到内存中然后进行处理。这很关键,因为您最终必须实现自己的进度条,因为您无法使用浏览器提供的本机进度条。这是 xhr 本身的一个缺点。

  • @KJSudarshan 你知道大文件的解决方案是什么吗?我目前遇到了这个问题 :(

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

    我在这里找到了一些很棒的解决方案。但它们通常没有考虑到 IE 浏览器的问题。也许这会为其他人节省一些时间。

    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 文件。

    response.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    
    response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exceptions.xlsx")
    
  • 引用 19

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

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

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

    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()
      })
    
  • 我使用 drf 作为后端,当我使用 postman 保存响应时。它将其保存到 excel 文件中,并完美打开所有数据 @roli roli

返回
作者最近主题: