前端很多项目中,都有文件下载的需求,特别是 JS 生成文件内容,然后让浏览器执行下载操作(例如在线图片编辑、在线代码编辑、iPresst 等)。
但受限于浏览器,很多情况下我们都只能给出个链接,让用户点击打开-》另存为。如下面这个链接:
<a href="file.js">file.js</a>
用户点击这个链接的时候,浏览器会打开并显示链接指向的文件内容,显然,这并没有实现我们的需求。
HTML5 中给 a 标签增加了一个 download 属性,只要有这个属性,点击这个链接时浏览器就不在打开链接指向的文件,而是改为下载(目前只有 chrome、firefox 和 opera 支持)。
下载时会直接使用链接的名字来作为文件名,但是是可以改的,只要给 download 加上想要的文件名即可,如:download=“not-a-file.js”。
Not enough!
但是这样还不够,以上的方法只适合用在文件是在服务器上的情况。如果在浏览器端 js 生成的内容,想让浏览器进行下载要如何办到呢?
其实还是有办法办到的,相信很多人都多少听过了 DataURI 这个词,比较常见的就是图片的 src,如:
<img src="
data:image/gif;base64,R0lGOXXXXX">
DataURI 的解释可以移步这里,本人就不在解释了。
那么,现在要将 js 生成的内容进行下载就有法可依了。封装成一个方法如下:
1 2 3 4 |
function downloadFile(aLink, fileName, content){ aLink.download = fileName; aLink.href = "data:text/plain," + content; } |
调用 downloadFile 之后,用户点击链接,就能触发浏览器下载。
Not enough!
但是,还不够,上面的办法有两个硬伤,会导致流失很多懒人美眉:
- 下载的文件类型限制死了,美眉要下载处理后的果照怎么办?
- 下载还要再点击一下,太麻烦啦。
要解决文件类型的问题,可以用浏览器的新 API(URL.createObjectURL)来解决问题,URL.createObjectURL 通常都是用来创建图片的 DataURI 用来显示图片,这里用来下载文件,让浏览器来帮我们设定好文件类型。
URL.createObjectURL 的参数是 File 对象或者 Blob 对象,File 对象也就是通过 input[type=file] 选择的文件,Blob 对象是二进制大对象,详细说明可参考这里。
现在,我们只要用 content 创建一个 ObjectURL 并赋值给 aLink 即可解决文件类型的限制问题。
文件的自动下载也挺好办,自己构建一个 UI 点击事件,再自动触发下,就能实现自动下载啦。
现在来看看最终代码:
1 2 3 4 5 6 7 8 9 |
function downloadFile(fileName, content){ var aLink = document.createElement('a'); var blob = new Blob([content]); var evt = document.createEvent("HTMLEvents"); evt.initEvent("click", false, false);//initEvent 不加后两个参数在FF下会报错, 感谢 Barret Lee 的反馈 aLink.download = fileName; aLink.href = URL.createObjectURL(blob); aLink.dispatchEvent(evt); } |
现在,只要一调用 downloadFile,文件就自动下载了,是不是很爽咧,^_^。
注:目前(2014-01-02)Blob 和 URL.createObjectURL 在标准浏览器里面都不再需要加私有前缀,可以放心使用啦啦啦~~如果你不放心,可以查查 Can I Use。
白一梓 2016 年 8 月 17 日
A DOM event generated from JavaScript has triggered a default action inside the browser. This behavior is non-standard and will be removed in M53, around September 2016. See https://www.chromestatus.com/features/5718803933560832 for more details. 调用 dispatchEvent 报错
不错的网站 | All Stack 2015 年 12 月 13 日
[…] 在浏览器端用 JS 创建和下载文件 […]
erayliu 2015 年 9 月 1 日
这里的浏览器兼容还是个问题
jQuery多文件下载 – Fly_Elephant | 查问题 2015 年 1 月 7 日
[…] 参考资料: 在浏览器端用 JS 创建和下载文件 AlloyTeam […]
jQuery多文件下载 | 易鸣 2015 年 1 月 7 日
[…] 参考资料: 在浏览器端用 JS 创建和下载文件 AlloyTeam […]
linusyu 2014 年 11 月 22 日
Firefox 不行。
用 MouseEvents 可以:
var evt = document.createEvent(“MouseEvents”);
evt.initMouseEvent(“click”, true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
kevin 2014 年 8 月 5 日
给定了文件名之后,点击下载,结果下载的文件名没有后缀且名称就是个 “下载”, chrome 浏览器,请问为何呢?
JavaScript多文件下载 | 0KS3iio'S Blog 2014 年 7 月 7 日
[…] 在浏览器端用 JS 创建和下载文件 AlloyTeam […]
scott 2014 年 4 月 25 日
我查了很多外国的相关,很多人都推荐 FileSaver.js,我试过三大浏览器的最新版都支持 —_—! 其他的就没试了
cathzhang 2014 年 3 月 3 日
firefox 下 event 事件应该为 MouseEvents
int01: Blog » 保存 JavaScript 变量到本地文件 2014 年 2 月 14 日
[…] 在浏览器端用 JS 创建和下载文件 | 腾讯 Web 前端 AlloyTeam 团队 Blog […]
Barret Lee 2014 年 2 月 13 日
http://www.cnblogs.com/hustskyking/p/multiple-download-with-javascript.html
对楼主的文章做了一点补充~ 兼容至 IE,FF 或 safari 暂时还未考虑,不过心中已有解决方案~
TAT.iAzrael 2014 年 2 月 14 日
感谢你的反馈 ^_^
xtgss 2014 年 10 月 8 日
我也在研究一块,safari 有解决方案了没
jaeger 2014 年 1 月 22 日
困扰我好长时间的问题了,现在终于知道怎么解决了,多谢 (●’◡’●)
【PowerfulJS】2~使用JS下载较大的文件 | 腾讯Web前端 AlloyTeam 团队 Blog 2014 年 1 月 8 日
[…] 康哥的《在浏览器端用 JS 创建和下载文件》, 这篇文章写的很不错,其中关于下载这部分,解决了一些困扰已久的问题,本文基本保存文件的基础,做一些新的尝试(当然,老外比我们走得早一些,已经将此方法用在站点上)[…]
Ciel 2014 年 1 月 16 日
Safari 不支持 download 标签。
TAT.iAzrael 2014 年 2 月 8 日
是啊, 我文中有说, 目前只有 chrome、firefox 和 opera 支持
szmy 2014 年 1 月 6 日
我想把 textarea 的内容当成一个文本文件下载下来
但用记事本打开后变成一行了
notepad++打开却保留了换行
这可能是什么原因引起的呢
还有用火狐调最后那个方法不会自动下载
TAT.iAzrael 2014 年 1 月 6 日
这是编辑器对换行符的解析问题吧, 你的 textarea 里生成的内容时之后\n 吧, notepad++可以正确识别成换行, 但是 window 自带的记事本只认\r\n 为换行, 你用 notepad++显示所有隐藏字符就能看出区别了. 火狐需要 25 以上的版本才支持 download,http://caniuse.com/#feat=download
szmy 2014 年 1 月 9 日
明白了
关于火狐那个我这儿是支持 download 属性,但在 dispatchEvent 后并没有下载
断点看 alink 的 download 属性和 href 属性都有
TAT.iAzrael 2014 年 1 月 9 日
可能是 firefox 的广告屏蔽插件禁止了自动触发的 click 事件
冷月无声 2014 年 1 月 6 日
什么情况下会用 js 创建文件呢?
TAT.iAzrael 2014 年 1 月 6 日
比如, 在线图片编辑器, 处理完图片之后, 让用户下载到电脑上, 例如这个: http://appx.imatlas.com/sketching/ , 还有在线编辑文档的网站, 如 google docs 等
xcv58 2014 年 1 月 5 日
Safari Version 7.0.1 (9537.73.11) 不支持?
TAT.iAzrael 2014 年 1 月 6 日
safari 现在不支持 download 属性
星情 2014 年 1 月 4 日
以前的资料说是出于安全考虑,浏览器默认不允许 JS 脚本创建文件呐,现在没这限制了?
TAT.iAzrael 2014 年 1 月 6 日
这里其实不是直接在用户硬盘上创建文件, 而是 js 创建了文件内容, 让浏览器弹出下载框而已 (如果勾选了默认保存, 则会自动下载)
likev 2014 年 5 月 26 日
firefox 29 貌似不能自动弹出下载框 IE11 也不行 Chrome34 可以
SaFly.ORG 2014 年 1 月 4 日
多好的技术博,怎么这么清净呢?
廖俊媛 2014 年 1 月 4 日
默默的做测试去