我使用axios的基本http请求,如GET和POST,它工作得很好。现在我需要能够下载Excel文件。这在axios中可行吗?如果是,谁有一些示例代码?如果不是,我还可以在React应用程序中使用什么来做同样的事情?
当前回答
使用URL.CreateObject()的答案对我来说工作得很好。 我仍然想指出使用HTTP报头的选项。
使用HttpHeaders有以下优点:
广泛的浏览器支持 不需要在浏览器的内存中创建一个blob对象 在显示给用户反馈之前,不需要等待服务器的完整响应吗 无尺寸限制
使用HttpHeaders需要你访问下载文件的后端服务器(这似乎是OP的Excel文件的情况)
HttpHeaders解决方案:
前端:
//...
// the download link
<a href="download/destination?parameter1=foo¶m2=bar">
click me to download!
</a>
后端
(本例中是c#,但也可以是任何语言。根据需要进行调整)
...
var fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Read);
Response.Headers["Content-Disposition"] = "attachment; filename=someName.txt";
return File(fs, "application/octet-stream");
...
此解决方案假定您可以控制响应的后端服务器。
https://github.com/eligrey/FileSaver.js/wiki/Saving-a-remote-file#using-http-header
其他回答
我有一个问题,我从axios const axiosResponse = await axios.get(pdf.url)传输到谷歌驱动器googleDrive.files。create({media: {body: axiosResponse.)data, mimeType}, requestBody: {name: fileName, parents: [parentFolder], mimeType}, auth: jwtClient})上传一个损坏的文件。
文件损坏的原因是axios转换了axiosResponse。数据转换为字符串。为了解决这个问题,我必须要求axios返回一个axios.get流。url, {responseType: 'stream'})。
下载带有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;但是,为了优化性能和内存使用,如果存在可以显式卸载它们的安全时间,则应该这样做。
诀窍是在render()中创建一个不可见的锚标记,并添加一个React ref,允许在我们有axios响应时触发单击:
class Example extends Component {
state = {
ref: React.createRef()
}
exportCSV = () => {
axios.get(
'/app/export'
).then(response => {
let blob = new Blob([response.data], {type: 'application/octet-stream'})
let ref = this.state.ref
ref.current.href = URL.createObjectURL(blob)
ref.current.download = 'data.csv'
ref.current.click()
})
}
render(){
return(
<div>
<a style={{display: 'none'}} href='empty' ref={this.state.ref}>ref</a>
<button onClick={this.exportCSV}>Export CSV</button>
</div>
)
}
}
以下是文档:https://reactjs.org/docs/refs-and-the-dom.html。你可以在这里找到类似的想法:https://thewebtier.com/snippets/download-files-with-axios/。
使用URL.CreateObject()的答案对我来说工作得很好。 我仍然想指出使用HTTP报头的选项。
使用HttpHeaders有以下优点:
广泛的浏览器支持 不需要在浏览器的内存中创建一个blob对象 在显示给用户反馈之前,不需要等待服务器的完整响应吗 无尺寸限制
使用HttpHeaders需要你访问下载文件的后端服务器(这似乎是OP的Excel文件的情况)
HttpHeaders解决方案:
前端:
//...
// the download link
<a href="download/destination?parameter1=foo¶m2=bar">
click me to download!
</a>
后端
(本例中是c#,但也可以是任何语言。根据需要进行调整)
...
var fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Read);
Response.Headers["Content-Disposition"] = "attachment; filename=someName.txt";
return File(fs, "application/octet-stream");
...
此解决方案假定您可以控制响应的后端服务器。
https://github.com/eligrey/FileSaver.js/wiki/Saving-a-remote-file#using-http-header
当响应带有可下载文件时,响应头将类似于
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');
});