方法一:a标签的download
采用原生创建dom节点的方法,注册a标签,把文件的地址放入 a标签的href里面。再通过js触发事件。
<div onClick={()=>{
this.handleDownLoad(record)
}}>
下载
</div>
handleDownLoad = async record =>{
let aEle = document.getElementById('aElement');
// 创建dom节点
if(!aEle){
try{
aEle = document.creatElement('<a name="aElement">');
}catch(e){
aEle = document.createElement('a')
}
}
// 把创建的dom节点挂载到dom树上
document.body.appendChild(aEle);
// 隐藏a标签
aEle.style.display = 'none';
aEle.href = 'https://xxxxx.com';
aEle.download = '文件名称';
aEle.click();
}
方法二:form表单提交
为一个下载按钮添加click事件,点击时动态生成一个表单,利用表单提交的功能来实现文件的下载
/**
* 下载文件
* @param {String} path - 请求的地址
* @param {String} fileName - 文件名
*/
function downloadFile (downloadUrl, fileName) {
// 创建表单
const formObj = document.createElement('form');
formObj.action = downloadUrl;
formObj.method = 'get';
formObj.style.display = 'none';
// 创建input,主要是起传参作用
const formItem = document.createElement('input');
formItem.value = fileName; // 传参的值
formItem.name = 'fileName'; // 传参的字段名
// 插入到网页中
formObj.appendChild(formItem);
document.body.appendChild(formObj);
formObj.submit(); // 发送请求
document.body.removeChild(formObj); // 发送完清除掉
}
方法三:open或location.href
本质上和a标签访问下载链接一样
window.open('downloadFile.zip');
location.href = 'downloadFile.zip';
方法四:Blob对象
调用api,将文件流转为Blob二进制对象, :::danger 注:IE10以下不支持。 ::: 思路: 发请求获取二进制数据,转化为Blob对象,利用URL.createObjectUrl生成url地址,赋值在a标签的href属性上,结合download进行下载。
/**
* 下载文件
* @param {String} path - 下载地址/下载请求地址。
* @param {String} name - 下载文件的名字/重命名(考虑到兼容性问题,最好加上后缀名)
*/
downloadFile (path, name) {
const xhr = new XMLHttpRequest();
xhr.open('get', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function () {
if (this.status === 200 || this.status === 304) {
// 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob
if ('msSaveOrOpenBlob' in navigator) {
navigator.msSaveOrOpenBlob(this.response, name);
return;
}
/*
如果发送请求时不设置xhr.responseType = 'blob',
默认ajax请求会返回DOMString类型的数据,即字符串。
此时需要使用两处注释的代码,对返回的文本转化为Blob对象,然后创建blob url,
此时需要注释掉原本的const url = URL.createObjectURL(target.response)。
*/
/*
const blob = new Blob([this.response], { type: xhr.getResponseHeader('Content-Type') });
const url = URL.createObjectURL(blob);
*/
const url = URL.createObjectURL(this.response); // 使用上面则注释此行
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
};
}
// 上面方法本地测试有时会有跨域问题,下面使用axios重写一下
// 已经配置好proxy
downloadFile (path, name) {
axios.get({
url: path,
method: 'get'
}).then(res => {
const blob = new Blob([res.data], { type: res.headers['content-type'] });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
})
}
该方法不能缺少a标签的download属性的设置。
因为发请求时已设置返回数据类型为Blob类型(xhr.responseType = ‘blob’),所以target.response就是一个Blob对象,打印出来会看到两个属性size和type。虽然type属性已指定了文件的类型,但是为了稳妥起见,还是在download属性值里指定后缀名,如Firefox不指定下载下来的文件就会不识别类型。
方法五:利用Base64
/**
* 下载文件
* @param {String} path - 下载地址/下载请求地址。
* @param {String} name - 下载文件的名字(考虑到兼容性问题,最好加上后缀名)
*/
downloadFile (path, name) {
const xhr = new XMLHttpRequest();
xhr.open('get', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function () {
if (this.status === 200 || this.status === 304) {
const fileReader = new FileReader();
fileReader.readAsDataURL(this.response);
fileReader.onload = function () {
const a = document.createElement('a');
a.style.display = 'none';
a.href = this.result;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
}
};
}