您现在的位置是:首页 > 文章详情

JavaScript tips —— 关于下载与导出的二三事

日期:2018-07-18点击:395

前言

在项目中经常会遇到下载或导出服务端资源的需求,一般分为2种做法
  1. 获取文件流,编码后下载
  2. 获取文件的url,直接下载
本文主要探讨第二种方法,在最后会提及文件流的方法。


浏览器的安全策略

在介绍方法之前,我们需要知道浏览器的一些安全机制,防止恶意代码对用户的破坏。
现代浏览器(ie8除外)检测到非用户直接操作产生的新窗口,一般会阻止,比如在ajax的回调中打开新的窗口,因为这些操作并不是在用户点击的线程中,所以会拦截。


预开新标签页

做法

  1. 在异步操作之前,先打开一个新标签页
  2. 请求后端资源的地址
  3. 获取url后去修改空白页的url

const downloadTab = window.open('about:blank'); ajax.get('xxx').then(url => { // 使用后端资源的url进行下载 downloadTab.location.href = href; }).catch(err => { // 处理异常 downloadTab.close(); }) 

缺点

  1. 不管请求成功还是失败都会有新页面的闪烁出现
  2. 打开的新页面在什么时候关闭是个问题,因为如果请求时间过长,用户可能自己关闭新页面,更不好处理的情况是页面什么时候触发了下载,因为如果只是更改url就关闭窗口可能还没有开始下载的操作。


生成iframe

做法

为了避免页面闪烁与关闭时机的问题,可以在当前页面使用动态创建iframe的方式,直接下载

ajax.get('xxx').then(href => { if (!href) { return; } if (!this.downIframe) { this.downIframe = document.createElement('iframe'); // 动态创建iframe this.downIframe.src = href; // iframe 中加载的页面 this.downIframe.id = 'downloadIframe'; // iframe 中加载的页面 this.downIframe.style.width = '1px'; this.downIframe.style.height = '1px'; this.downIframe.style.position = 'absolute'; this.downIframe.style.left = '-100px'; document.body.appendChild(this.downIframe); // 添加到当前窗体 } else { this.downIframe.src = href; // iframe 中加载的页面 } }).catch(err => { // 处理异常 }) 

缺点

虽然可以优雅的下载文件了,可是如果需要定制下载文件的名称就会令人头疼了,我们需要时机去改变下载文件的名称,否则就会使服务端的文件名称。


生成标签

利用download属性设置文件名,


0ca6df19dff4c25687376d33742502ab527eddfc


ajax.get('xxx').then(href => { if (!href) { return; } var a = document.createElement('a'); var url = href; var filename = 'test.zip'; a.href = url; a.download = filename; // 在没有download属性的情况,target="_blank",仍会阻止打开 a.click(); }).catch(err => { // 处理异常 }) 

注意:
有些浏览器需要将a标签嵌入页面才可执行。


处理文件流

最后大概讲一下如果后端返回流怎么处理。


function funDownload(content, filename) { // 创建隐藏的可下载链接 var link = document.createElement('a'); link.download = filename; link.style.display = 'none'; // 字符内容转变成blob地址 var blob = new Blob([content]); //如果是excel格式 //var blob = new Blob([content], {type: 'application/vnd.ms-excel'}), link.href = URL.createObjectURL(blob); // 触发点击 document.body.appendChild(link); link.click(); // 然后移除 document.body.removeChild(link); }; 

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。


注意:
在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。


原文发布时间为:2018年06月15日
原文作者:nanchenk

本文来源: 掘金 如需转载请联系原作者



原文链接:https://yq.aliyun.com/articles/615479
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章