今天写这篇文章是记录一下项目上之前没踩过的前端下载的坑,发出来希望大家可以给点意见或者自取其用~
一、GET下载
这种下载方式通常比较常见
1、可以使用a标签进行下载
<a href='下载文件的url' download>点我下载</a>
<a href='下载文件的url' download='文件名.(后缀名)'>点我下载</a>
href就是你要下载的地址,需要的是全路径,在后端的服务器上;
download还可以修改文件下载后的名字和类型,如果不需要修改后缀名,可不写;
2、window.open开启新tab下载
window.open('目标url')
// 携带参数
window.open(`目标url?a=111&b=${xxx}`)
该方法通过winodw.open打开新的tab,利用浏览器无法解析的资源会变成下载的特性来实现功能,api也不复杂
也可以携带参数
3、已知文件内容,通过URL.createObjectURL()下载文件
const onDownload = (url, fileName) => {
const x = new XMLHttpRequest();
x.open('GET', url, true);
x.responseType = 'blob';
// 监听进度
x.onprogress = (e) => {
if (e.lengthComputable) {
// 文件总体积
console.log('文件总体积', e.total);
// 已下载体积
console.log('已下载体积', e.loaded);
}
};
x.onload = () => {
const url = window.URL.createObjectURL(x.response);
const a = document.createElement('a');
a.href = url;
a.download = fileName;
a.click();
a.remove();
// 释放
window.URL.revokeObjectURL(url);
};
x.send();
};
当点击下载按钮时,请求接口,返回文件流。
URL.createObjectURL()静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
createObjectURL()支持传入 File 对象、Blob 对象或者 MediaSource 对象(媒体资源)。
4、使用FileReader进行下载
/**
* 下载文件
* @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);
};
}
};
}
二、POST下载
post下载一般有2种形式,第一种通过请求接口获取一个完整的文件下载路径,然后再通过window.open()的方式进行下载;第二种后端返回的文件流,前端通过解析文件流的方式进行下载。
1、后端返回完整链接下载
这种下载方式就比较简单了,直接使用项目封装的fetch去请求接口,拿到返回结果直接使用window.open下载即可
2、文件流下载
后台返回文件流,前端解析完成之后下载
下载csv格式
/* eslint-disable comma-dangle */
/* eslint-disable arrow-parens */
import moment from 'moment';
// 接口返回文件流,前端进行处理
export function downloadFromFileBuffer(
fileType = 'application/csv',
fileEncode = 'Unicode(UTF-8)',
fileName = `${moment().format('YYYYMMDDHHmmss')}.csv`,
content,
) {
const blob = new Blob([fileType === 'application/csv' ? `\uFEFF${content}` : content], {
type: `${fileType};charset=${fileEncode}`,
});
const a = document.createElement('a');
const URL = window.URL || window.webkitURL;
const herf = URL.createObjectURL(blob);
a.href = herf;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(herf);
}
// 请求接口内容
request(
'/api',
{
method: 'POST',
body: params,
},
false,
true,
).then((ret) => {
downloadFromFileBuffer('application/csv', 'Unicode(UTF-8)', `终端安全事件-${moment().format('YYYYMMDDHHmmss')}.csv`, ret);
}).finally(() => {
setSubmitting(false);
});
下载xlsx格式
fetch(`/api`, {
method: 'POST',
body: JSON.stringify(params),
headers: {
...setCommonHeader({}),
responseType:'blob', // 重要,一定要写,不然乱码无法解析导致文件损坏无法打开
'Content-type': 'application/json;charset=UTF-8',
Authorization: localStorage.getItem('token'),
}
})
.then((res) => res.blob())
.then((data) => {
const blobUrl = window.URL.createObjectURL(data);
const a = document.createElement('a');
a.download = `威胁狩猎-${moment().format('YYYYMMDDHHmmss')}.${type}`;
a.href = blobUrl;
a.click();
});