实现JS监听文件下载完成的功能(解决不同浏览器的下载触发 + a标签base64url过长无法下载的问题) 您所在的位置:网站首页 浏览器拦截js文件怎么打开 实现JS监听文件下载完成的功能(解决不同浏览器的下载触发 + a标签base64url过长无法下载的问题)

实现JS监听文件下载完成的功能(解决不同浏览器的下载触发 + a标签base64url过长无法下载的问题)

2024-07-11 23:09| 来源: 网络整理| 查看: 265

一般来说,我们的js文件下载会使用window.location.href定位到后端的接口,后端生成文件返回,然后浏览器自动下载。这种方法最简单,但是无法获取下载成功的通知,在大文件生成和下载的时候,时间过长,用户可能会重复进行下载的点击,对服务器造成负担。

因此要用另外的方式发送请求来监听文件下载完成,此方法使用的是XMLHttpRequest来请求,可以监听文件下载完成,另外一提,如果要对下载使用进度条监听的话,可以使用设置cookie循环向后端请求获取进度的方法,本文只讨论前者。

不多bb,直接开始

这是我一开始的版本:

load = function() { //填写你的下载时加载的提示 } disload = function() { //下载完成后触发,用来关闭提示框 } getDownload = function(url) { load(); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可用POST方式 xhr.responseType = "blob"; xhr.onload = function () { if (this.status === 200) { var blob = this.response; var reader = new FileReader(); reader.readAsDataURL(blob); reader.onload = function (e) { var headerName = xhr.getResponseHeader("Content-disposition"); var fileName = decodeURIComponent(headerName).substring(20); var a = document.createElement('a'); a.download = fileName + ".xls"; a.href = e.target.result; $("body").append(a); // 修复firefox中无法触发click a.click(); $(a).remove(); }; disload(); } }; xhr.send() };

这个原理是通过XMLHttpRequest发送请求,利用FileReader来读取文件内容,关键是设置a标签,将blob的文件内容转换为base64并放入a标签的href中,模拟点击来进行下载。

但是需要注意的是 a标签的download经测试,仅在谷歌和火狐浏览器生效,在edge和IE下不触发下载如果以base64为a标签的url地址的话,由于长度限制最多只能下载大约2M的文件,再高的话就会下载失败 第一个问题

对于ie等浏览器来说,有另外的一种方法来触发下载。

function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } //e.target.result 正是上面代码中转换后的baseUrl,这种方法要转换为blob var blob = dataURLtoBlob(e.target.result); navigator.msSaveBlob(blob, fileName + ".xls");

需要注意的是navigator.msSaveBlob在谷歌等浏览器中并不存在,在此,就解决了第一个问题

第二个问题

第二个问题其实也看需求,对于非常小的文件,比如小图标等可以用base64作为url地址,对于其他的大文件,可以将文件存入内存中,用虚拟内存地址指向。

var blob = dataURLtoBlob(e.target.result); var a = document.createElement('a'); a.download = fileName + ".xls"; a.href = URL.createObjectURL(blob); $("body").append(a); // 修复firefox中无法触发click a.click(); URL.revokeObjectURL(a.href); $(a).remove();

URL.createObjectURL 将blob形式的文件存入并返回一个url以供下载。 而URL.revokeObjectURL则将该内存释放。 至此,两个问题解决,可以看到大文件根本不能使用base64,直接使用blob是最好的。因此合并起来就可以得到最终版本了:

最终版本 load = function() { //填写你的下载时加载的提示 } disload = function() { //下载完成后触发,用来关闭提示框 } getDownload = function(url) { load(); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可用POST方式 xhr.responseType = "blob"; xhr.onload = function () { if (this.status === 200) { var blob = this.response; if (navigator.msSaveBlob == null) { var a = document.createElement('a'); var headerName = xhr.getResponseHeader("Content-disposition"); var fileName = decodeURIComponent(headerName).substring(20); a.download = fileName; a.href = URL.createObjectURL(blob); $("body").append(a); // 修复firefox中无法触发click a.click(); URL.revokeObjectURL(a.href); $(a).remove(); } else { navigator.msSaveBlob(blob, fileName); } } disload(); }; xhr.send() };


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有