我使用axios的基本http请求,如GET和POST,它工作得很好。现在我需要能够下载Excel文件。这在axios中可行吗?如果是,谁有一些示例代码?如果不是,我还可以在React应用程序中使用什么来做同样的事情?


当前回答

这个函数将帮助您下载一个现成的xlsx, csv等文件下载。我只是从后端发送一个就绪的xlsx静态文件,它在反应。

const downloadFabricFormat = async () => {
    try{
      await axios({
        url: '/api/fabric/fabric_excel_format/',
        method: 'GET',
        responseType: 'blob',
      }).then((response) => {
         const url = window.URL.createObjectURL(new Blob([response.data]));
         const link = document.createElement('a');
         link.href = url;
         link.setAttribute('download', 'Fabric Excel Format.xlsx');
         document.body.appendChild(link);
         link.click();
      });
    } catch(error){
      console.log(error)
    }
  };

其他回答

下载文件(使用Axios和Security)

当您希望使用Axios和一些安全手段下载文件时,这实际上更加复杂。为了防止其他人花太多时间来弄清楚这个问题,让我来给你介绍一下。

你需要做三件事:

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

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

1. 配置您的HTTP服务器

当使用传输安全性时,在浏览器中执行的JavaScript(根据设计)只能访问HTTP服务器实际发送的6个HTTP头。如果我们想让服务器为下载建议一个文件名,我们必须通知浏览器,它是“OK”的JavaScript被授予访问其他头,建议的文件名将被传输。

为了便于讨论,让我们假设服务器在一个名为X-Suggested-Filename的HTTP报头中传输建议的文件名。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。

2. 实现服务器端服务

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

创建(二进制)文档并将正确的ContentType分配给响应 为客户端分配包含建议文件名的自定义头文件(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.为Received文档实现一个Axios处理程序

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

服务响应@GET(即HTTP GET),因此Axios调用必须是' Axios . GET(…)'。 文档以字节流的形式传输,因此必须告诉Axios将响应视为HTML5 Blob。(例如responseType: 'blob')。 在本例中,文件保护程序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);
        });

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

Content-Disposition: "attachment;filename=report.xls"
Content-Type: "application/octet-stream" // or Content-type: "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回购

const FileDownload = require('js-file-download');

Axios({
  url: 'http://localhost/downloadFile',
  method: 'GET',
  responseType: 'blob', // Important
}).then((response) => {
    FileDownload(response.data, 'report.csv');
});

这个函数将帮助您下载一个现成的xlsx, csv等文件下载。我只是从后端发送一个就绪的xlsx静态文件,它在反应。

const downloadFabricFormat = async () => {
    try{
      await axios({
        url: '/api/fabric/fabric_excel_format/',
        method: 'GET',
        responseType: 'blob',
      }).then((response) => {
         const url = window.URL.createObjectURL(new Blob([response.data]));
         const link = document.createElement('a');
         link.href = url;
         link.setAttribute('download', 'Fabric Excel Format.xlsx');
         document.body.appendChild(link);
         link.click();
      });
    } catch(error){
      console.log(error)
    }
  };

下载带有Axios的文件作为responseType: 'blob' 使用Axios/Server响应中的blob创建文件链接 创建<a> HTML元素,使用href链接到步骤2中创建的文件链接,并单击该链接 清理动态创建的文件链接和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在MDN上可用。释放带有URL的对象非常关键。revokeObjectURL防止内存泄漏。在上面的函数中,因为我们已经下载了文件,所以可以立即撤销对象。

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

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

对于axios POST请求,请求应该是这样的: 这里的关键是responseType和header字段必须在Post的第3个参数中。第二个参数是应用程序参数。

export const requestDownloadReport = (requestParams) => async dispatch => { 
  let response = null;
  try {
    response = await frontEndApi.post('createPdf', {
      requestParams: requestParams,
    },
    {
      responseType: 'arraybuffer', // important...because we need to convert it to a blob. If we don't specify this, response.data will be the raw data. It cannot be converted to blob directly.
      headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/pdf'
      }
  });          
  }
  catch(err) {
    console.log('[requestDownloadReport][ERROR]', err);
    return err
  }

  return response;
}