本文转载自:www.zhangxinxu.com/wordpress/?…
一、HTML 与文件下载
如果希望在前端侧直接触发某些资源的下载,最方便快捷的方法就是使用 HTML5 原生的download
属性,例如:
bash
<a href="large.jpg" download>下载</a>
具体介绍可参考我之前的文章:“了解 HTML/HTML5 中的 download 属性”。
但显然,如果纯粹利用 HTML 属性来实现文件的下载(而不是浏览器打开或浏览),对于动态内容,就无能为力。
例如,我们对页面进行分享的时候,希望分享图片是页面内容的实时截图,此时,这个图片就是动态的,纯 HTML 显然是无法满足我们的需求的,借助 JS 和其它一些 HTML5 特性,例如,将页面元素转换到canvas
上,然后再转成图片进行下载,可参见 “SVG 简介与截图等应用” 一文。
但本文要介绍的下载不是图片的下载,而是文本信息的下载,所需要使用的 HTML 特性不是canvas
,而是其它。
二、借助 HTML5 Blob 实现文本信息文件下载
如果对 Blob 不了解,可以先看看我好些年之前写的 “理解 DOMString、Document、FormData、Blob、File、ArrayBuffer 数据类型” 一文。
原理其实很简单,我们可以将文本或者 JS 字符串信息借助 Blob 转换成二进制,然后,作为<a>
元素的href
属性,配合download
属性,实现下载。
代码也比较简单,如下示意(兼容 Chrome 和 Firefox):
var funDownload = function (content, filename) {
// 创建隐藏的可下载链接
var eleLink = document.createElement('a');
eleLink.download = filename;
eleLink.style.display = 'none';
// 字符内容转变成blob地址
var blob = new Blob([content]);
eleLink.href = URL.createObjectURL(blob);
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
};
其中,content
指需要下载的文本或字符串内容,filename
指下载到系统中的文件名称。
万般言语不达意,一枚实例来走心。
您可以狠狠地点击这里:基于 funDownload 实现的 html 格式文件下载 demo
点击 “下载” 按钮,会把文本域中的内容全部作为一个.html
后缀文件下载下来,各流程效果如下面几张图:
出现下载确认框(根据浏览器的设置不同也可能直接下载),然后名称默认就是test.html
。
然后对应保存目录就多了个类似下图的文件:
双击该test.html
文件可以在浏览器中正常浏览,说明,保存信息无误。
触发下载的 JS 代码就几行:
button.addEventListener('click', function () {
funDownload(textarea.value, 'test.html');
});
三、借助 Base64 实现任意文件下载
对于非文本文件,也是可以直接 JS 触发下载的,例如,如果我们想下载一张图片,可以把这张图片转换成 base64 格式,然后下载。
代码示意:
var funDownload = function (domImg, filename) {
// 创建隐藏的可下载链接
var eleLink = document.createElement('a');
eleLink.download = filename;
eleLink.style.display = 'none';
// 图片转base64地址
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var width = domImg.naturalWidth;
var height = domImg.naturalHeight; context.drawImage(domImg, 0, 0);
// 如果是PNG图片,则canvas.toDataURL('image/png')
eleLink.href = canvas.toDataURL('image/jpeg');
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
};
四、结束语
不止是.html
文件,.txt
, .json
等文本文件都可以使用这种小技巧实现下载。
在Chrome浏览器下,模拟点击创建的<a>
元素即使不append
到页面中,也是可以触发下载的,但是在Firefox浏览器中却不行,因此,上面的funDownload()
方法有一个appendChild
和removeChild
的处理,就是为了兼容Firefox浏览器。
download
属性从Edge13开始支持,根据同行测试可以触发下载,不过生成的文件命名类似GUID,需要手动再加个后缀。
就这些,感谢阅读!