一个很普遍的场景,我要下载一个文件,这个文件是后端通过一定的逻辑生成的,需要一定的等待时间,所以点击下载后,要呈现等待状态,等下载完了,就把等待状态去掉
第一步,下载文件,我们可以用iframe来实现(有些同学可能会说你可以把文件内容下载到本地,用Blob封装成一条URL,模拟点击就行了,类似的实现方案如js-file-download。但试过如果是zip文件会出现解压不了的情况)
let link = document.createElement('iframe');
link.src = '/your/file/path/name.zip';
link.style.display = 'none';
document.body.appendChild(link);
很简单吧,接下来需要增加等待状态,然后监听下载完成事件。这不是很简单吗?监听iframe的onload事件即可,撸下代码如下:
let link = document.createElement('iframe');
link.src = '/your/file/path/name.zip';
link.style.display = 'none';
document.body.appendChild(link);
link.addEventListener('load', () => {
console.log('还不简单,这就下载完成了')
document.body.removeChild(link);
})
试下运行一下,咦,不work哦,文件是下载下来了,但load事件没进去,昨肥事呢?原因是chrome(不同浏览器可能表现不一样,这里只针对是前端开发人员都会用的chrome)只对html的加载作load监听,而对于下载文件,是不会触发load事件的
那昨办呢?其实还真不好办,当然这篇文章写了这么多,不给提供方案,不是找抽吗?
换个思路,我们就是要提供一个标识,让前端知道下载完成的状态,那可以通过cookie啊。
我们可以在下载文件的response设置Set_Cookie header,比如nginx的配置如下:
add_header Set-Cookie "fileDownloaded=1; path=/;" always;
然后前端就可以通过定时去判断有没该cookie值来判断是否下载完成,代码如下:
let interval = setInterval(() => {
if (Cookies.get('fileDownloaded')) { // 通过判断是否有这个cookie来确定是否下载完成
console.log('下载完成啦')
clearInterval(interval);
}
}, 500);`
以下附上完整代码
let link = document.createElement('iframe');
link.src = '/your/file/path/name.zip';
link.style.display = 'none';
document.body.appendChild(link);
let interval = setInterval(() => {
if (Cookies.get('fileDownloaded')) { // 通过判断是否有这个cookie来确定是否下载完成
console.log('下载完成啦')
clearInterval(interval);
document.body.removeChild(link);
Cookies.remove('genProjectDownloaded');
}
}, 500);`
过程虽然曲折,但最终是实现了想要的效果,如果有更好的方案,还请不吝赐教
网友评论