写在前面:网上关于前端实现文件下载的文章已经有很多了,而且有的写的十分详细专业。之前一直不愿意做此类记录,一来是觉得这方面的文章太多太详细了,没有写的必要;二来是想着自己写的还不一定有别人写的好。但随着日常开发中用到的文件下载功能用的越多,各种下载方式都有使用过,觉得需要记录一下,以方便使用。
1、form 表单下载
1.1、表单下载基本使用
form 表单下载是比较传统的下载方式,话不多说,直接看实例:
function formDownload(data){ // data :<object> form 表单的传参
let form = document.createElement('form');
form.id = 'idForm';
form.name = 'name_form';
form.style.display = 'none';
document.body.appendChild(form);
for (let i in data) {
if (i !== 'action') {
let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
input.type = 'text';
input.name = i;
input.value = data[i];
form.appendChild(input);
} else {
continue;
}
}
form.method = 'get';
form.action = URL; // form 表单发送的地址
form.submit();
document.body.removeChild(form);
}
- 表单的提交就相当于一次请求,input 中的值相当于传参
- form 上有一个属性 target,这个属性指定返回结果放的位置,默认 _self 表示本页面
- 浏览器可以识别的文件不能下载:txt、png、jpg、gif等
- 无法获取下载进度
- 可以避免URL过长问题
1.2、 表单下载通过 iframe 接收返回信息并实现无刷新
将 form.target 设置成 iframe ,可以获取返回的信息,完整代码:
function formDownload(data) { // data :<object> form 表单的传参
var target = 'sub_frame' + Date.parse(new Date());
var iframe = document.createElement('iframe');
iframe.src = window.location.href;
iframe.name = target;
iframe.id = target;
iframe.width = 0;
iframe.height = 0;
iframe.style.display = 'none'
document.body.appendChild(iframe);
let form = document.createElement('form');
form.id = 'idForm';
form.name = 'name_form';
form.setAttribute("target", target);
form.style.display = 'none';
document.body.appendChild(form);
for (let i in data) {
if (i !== 'action') {
let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
input.type = 'text';
input.name = i;
input.value = data[i];
form.appendChild(input);
} else {
continue;
}
}
form.method = 'get';
form.action = URL; // form 表单发送的地址
form.submit();
document.body.removeChild(form);
// 通过循环去拿返回数据
var count = 0;
var timer = setInterval(function () {
var iframeObj = $(window.frames[target].document);
var val = iframeObj.find("pre").text();
count++;
if (count >= 60) {
window.clearInterval(timer);
document.body.removeChild(iframe);
return false
}
if (val) {
var res = JSON.parse(val);
window.clearInterval(timer);
document.body.removeChild(iframe);
}
}, 1000)
}
2、直接跳转下载
2.1、location.href
window.location.href = url;
2.2、window.open
window.open(url);
- 以上两种适合 get 请求的单文件下载
- 会出现 url 过长的问题,需要注意 url 编码
- 浏览器可以识别的文件不能下载:txt、png、jpg、gif等
3、a链接下载
let a = document.createElement('a');
a.style = 'display: none';
a.download = filename;
a.href = url;
document.body.appendChild(a);
a.click(); // 触发a标签的click事件
document.body.removeChild(a);
这种方式也无法解决浏览器可识别文件直接打开的问题,但是 HTML5 新属性 download 属性会解决这个问题。
但是也会有局限:部分情况下会出现跨域问题,此时还是浏览器预览而非下载,download属性失效。可以用这个方法试一下文本、图片。
部分浏览器由于兼容性问题(一般不会出现):
const isSupport = 'download' in document.createElement('a');
看支不支持 download 属性
** 4、文件流下载之 blob + a 链接 + blob URL**
let xhr = new XMLHttpRequest();
xhr.open('GET', videoUrl, true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (xhr.status === 200) {
// 将视频Blob对象创建一个临时URL
let videoBlob = xhr.response;
let url = window.URL.createObjectURL(videoBlob);
// 设置a标签的属性,并触发点击事件进行下载
a.href = url;
a.download = fileName; //文件名
a.click();
// 释放URL对象
window.URL.revokeObjectURL(url);
a.remove()
}
};
xhr.send();
发送 http 请求,指定返回值类型是 blob 流
建议加上 download 的后缀名,避免极个别浏览器无法识别
这种实现本质是通过 blob URL方式
可通过 xhr.getResponseHeader("Content-Disposition") 获取 header 上的 Content-Disposition 属性,通过截取得到文件名
5、** 文件流下载之 blob + a 链接 + **readAsDataURL
let xhr = new XMLHttpRequest();
xhr.open('GET', videoUrl, true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (xhr.status === 200) {
// 将视频Blob对象创建一个临时URL
let videoBlob = xhr.response;
const fileReader = new FileReader();
fileReader.readAsDataURL(videoBlob);
fileReader.onload = function () {
const a = document.createElement('a');
a.style.display = 'none';
// 结果本质上是 base64 编码的 data URL 格式
a.href = fileReader.result;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}
};
xhr.send();
这个方法和上个 方法都是获取 blob 形式的返回值,只是结果处理方式不同,这种方式是通过 readAsDataURL 生成 base64 编码的 Data URL 再通过连接下载。
两种方法都可以解决 浏览器直接打开无法下载的问题
版权归原作者 Wu Youlu 所有, 如有侵权,请联系我们删除。