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


当前回答

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

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');
});

其他回答

文件下载自定义头请求。在这个例子中,它展示了如何用承载令牌发送文件下载请求。适合授权下载内容。

下载(urlHere) { axios。get (urlHere, { 标题:{ “Access-Control-Allow-Origin”:“*”, 授权:'持有人${sessionStorage.getItem("auth-token")} ', } }).then((response) => { const temp = window.URL。createObjectURL(新团([response.data])); const link = document.createElement('a'); 链接。Href = temp; 链接。setAttribute(“下载”,“file.csv”);//或任何其他扩展 document.body.appendChild(链接); link.click (); }); }

这是为用户触发下载的非常简单的javascript代码:

window.open("<insert URL here>")

这个操作不需要axios;它应该是标准的,只是让浏览器做它的事情。

注意:如果您需要授权下载,那么这可能无法工作。我很确定你可以使用cookie来授权这样的请求,前提是它在同一个域中,但不管怎样,在这种情况下,这可能不会立即起作用。


至于是否可能……没有内置的文件下载机制,没有。

使用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()
  })

实现接收文档的Axios处理程序,数据格式为octect-stream, 数据可能看起来很奇怪PK一些JbxfFGvddvbdfbVVH34365436fdkln作为它的八字节流格式,你可能最终会创建这个数据可能被损坏的文件,{responseType: 'blob'}将数据转换为可读格式,

axios.get("URL", {responseType: 'blob'})
     .then((r) => {
         let fileName =  r.headers['content-disposition'].split('filename=')[1];
         let blob = new Blob([r.data]);
         window.saveAs(blob, fileName);             
      }).catch(err => {
        console.log(err);
      });

你可能尝试过这样的解决方案, 窗口。saveAs(blob, 'file.zip')将尝试将文件保存为zip,但将不会工作,

const downloadFile = (fileData) => {
    axios.get(baseUrl+"/file/download/"+fileData.id)
        .then((response) => {
            console.log(response.data);
            const blob = new Blob([response.data], {type: response.headers['content-type'], encoding:'UTF-8'});
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = 'file.zip';
            link.click();
        })
        .catch((err) => console.log(err))
}
const downloadFile = (fileData) => {
axios.get(baseUrl+"/file/download/"+fileData.id)
    .then((response) => {
        console.log(response);
        //const binaryString = window.atob(response.data)
        //const bytes = new Uint8Array(response.data)
        //const arrBuff = bytes.map((byte, i) => response.data.charCodeAt(i));
        //var base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(response.data)));
        const blob = new Blob([response.data], {type:"application/octet-stream"});
        window.saveAs(blob, 'file.zip')
        // const link = document.createElement('a');
        // link.href = window.URL.createObjectURL(blob);
        // link.download = 'file.zip';
        // link.click();
    })
    .catch((err) => console.log(err))
}
function base64ToArrayBuffer(base64) {
    var binaryString = window.atob(base64);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++) {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    };

    return bytes;
}

另一个简单的解决方法是,

window.open("URL")

将继续打开不必要的新选项卡,用户可能不得不让允许弹出的工作这段代码,如果用户想同时下载多个文件,所以先去解决方案或如果不尝试其他解决方案也怎么办

对于那些想要实现经过身份验证的本地下载的人。

我目前正在使用Axios开发一个SPA。 不幸的是,Axios在这种情况下不允许流响应类型。 从文档:

// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'

但我想出了一个解决办法,就像在这个话题中提到的那样。 诀窍是发送一个包含令牌和目标文件的基本Form POST。

这是针对一个新的窗口。一旦浏览器读取服务器响应上的附件标头,它将关闭新选项卡并开始下载。”

下面是一个例子:

let form = document.createElement('form');
form.method = 'post';
form.target = '_blank';

form.action = `${API_URL}/${targetedResource}`;
form.innerHTML = `'<input type="hidden" name="jwtToken" value="${jwtToken}">'`;

document.body.appendChild(form);
form.submit();
document.body.removeChild(form);

“您可能需要将处理程序标记为未验证/匿名,以便手动验证JWT以确保适当的授权。”

结果是我的ASP。NET实现:

[AllowAnonymous]
[HttpPost("{targetedResource}")]
public async Task<IActionResult> GetFile(string targetedResource, [FromForm] string jwtToken)
{
    var jsonWebTokenHandler = new JsonWebTokenHandler();

    var validationParameters = new TokenValidationParameters()
    {
        // Your token validation parameters here
    };

    var tokenValidationResult = jsonWebTokenHandler.ValidateToken(jwtToken, validationParameters);

    if (!tokenValidationResult.IsValid)
    {
        return Unauthorized();
    }

    // Your file upload implementation here
}