前端文件下载方式总结

Wu Youlu 2024-07-26 12:03:04 阅读 60

写在前面:网上关于前端实现文件下载的文章已经有很多了,而且有的写的十分详细专业。之前一直不愿意做此类记录,一来是觉得这方面的文章太多太详细了,没有写的必要;二来是想着自己写的还不一定有别人写的好。但随着日常开发中用到的文件下载功能用的越多,各种下载方式都有使用过,觉得需要记录一下,以方便使用。

1、form 表单下载

1.1、表单下载基本使用

form 表单下载是比较传统的下载方式,话不多说,直接看实例:

<code>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 再通过连接下载。

两种方法都可以解决 浏览器直接打开无法下载的问题



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。