先看 Demo 点击这里
康哥的 《在浏览器端用 JS 创建和下载文件》, 这篇文章写的很不错,其中关于下载这部分,解决了一些困扰已久的问题,本文基于保存文件的基础上,做一些新的尝试(当然,老外比我们走得早一些,已经将此方法用在站点上)
直接切入正题。
传统浏览器下载文件
传统浏览器下载文件,一般都是浏览器直接下载文件,我们以前无法做到
- 监控文件的下载进度和速度
- 控制文件下载的行为(暂时 or 停止)
如今,PowerfulJs 使我们做到了上述能力,可以预见,Web 版的类迅雷的工具也将会出现了
实现原理
其实原理也是很简单的,简单说来,我们使用 Ajax 来请求文件,并可以用事件来监测我们下载了多少,一共有多少需要下载,这样也可以算出下载的速度(当然这里还可以做 Web 版网速测试工具),然后再用文件保存方法将其保存下来就可以了
当然这些功能,是要依赖于 XHR2 的能力的
具体的实现细节如下
设置 responseType 为 blob
1 2 3 4 5 6 7 8 |
var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (success) success(xhr.response); } }; |
然后监听下载的 process 事件
1 2 3 4 |
xhr.addEventListener("progress", function(e){ //e.total就是文件的总字节 e.loaded就是文件已加载了多少字节了 }); xhr.send(); |
下载文件
这里下载文件的方法具体可以参考康哥的上篇文章,这里我们使用一个老外封装好的库 FileSaver.js 来下载文件
1 2 |
//saveAs是FileSaver.js中的方法 saveAs(blobData, "test.mp3"); |
浏览器表现
由于机器上没有 Firefox,没有 Firefox 的测试结果
Chrome: 显示下载进度,成功下载后,如果对于一般文件会直接保存,如下图,注意这里的顺序,这里是先下载完成,浏览器出现下图的时候是直接保存完成的!
对于一般的文件,chrome 不会有提示
对于敏感的文件,chrome 会提示是否保留或放弃
IE11 下表现:
IE11 下表现也是很乖的,完全可以运行,便其不管什么文件都会提示是否保存
victoria 2017 年 7 月 10 日
首先感谢您的分享,简单的尝试了下,文件可以正常下载。方法简介明了。但是我还有两个问题没有解决:
1. 这个方法对文件大小有限制么?
2. 利用这个方法怎样实现文件分块下载(假设每次请求,服务器只返回文件的一部分数据)么?
璠 2017 年 3 月 9 日
if (success) success(xhr.response); 请问这句是什么意思,为什么 success 可以放到 if 括号里,后面 success 怎么又成函数了?后面调用函数的时候,success 怎么又替换成函数了。请大神解答。
Mr.zhan 2014 年 3 月 22 日
刚刚测试了一下请求服务器的数据,类型为 json,progress 返回值中只有 loaded 没有 total
请问是为什么呢,这样没办法用作进度条的
电丶灵 2014 年 2 月 20 日
类迅雷的 WEB 下载器感觉没啥用
原因如下:
1、浏览器要崩溃就白下了,我觉得没办法做到断点续传功能(应该这么叫吧)
2、没有下载加速(毕竟是以浏览器为媒介)
3、没有离线下载功能
如果能做到这三点,到还有作用
Tian 2014 年 1 月 11 日
我下了 Demo 测试了下,好像只能下载当前域的文件,远程文件下载不了。
ijse 2014 年 2 月 6 日
需要配置 HTTP header 解决跨域问题
gacia 2014 年 5 月 13 日
求教,如何解决跨域问题呢?