前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,如今前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提高技术水平,打牢基础知识的中心思想,咱们开课啦(每周四)。html
这两天,碰到了不止一次前端下载的的问题。其实以前我写过一篇文章 download使用浅析,主要依靠 download
属性来实现浏览器端下载,由于是走浏览器的下载,因此没有进度条。今天咱们就来讲说个人解决方案。前端
download使用浅析 这一文中已经介绍了,能够去看看。我这里简单说一下。<a>
标签若是设置了 download
属性,他就会去下载这个地址。测试地址-原生 download 属性测试。ajax
下载文件上面已经实现了,那咱们先说说如何显示进度条。segmentfault
其实浏览器也是有进度条的,可是我们拿不到。那咱们就来模拟一下载,而后显示进度条。api
ajax
实现下载进度条,测试地址-显示进度条数组
xhr = new XMLHttpRequest(); xhr.open('get', file1.url); xhr.onprogress = (e)=>console.log(e)//e 就是一个 ProgressEvent 对象,其中 loaded 是已下载的, total 是总大小。 xhr.send()
fetch
实现下载进度条,测试地址-fetch显示进度条并下载fetch
的实现上来讲有一些功能是没有的,好比 abort
、进度等。那咱们就须要去经过一些别的手段来模拟实现。进度条已经显示好了,那咱们能够下载文件了。首先咱们要分几种状况浏览器
本地下载(资源已经在浏览器中)缓存
blob
url 下载 如这种地址 blob:https://www.lilnong.top/deb4c297-821c-4545-9b23-0fbdd76890c7
base64
url 下载 如这种地址 data:application/octet-stream;base64,aGVsbG8gbGlub25n
服务器
blob = new Blob(['hello linong']) freader = new FileReader() freader.readAsDataURL(blob)//将 blob 读成 dataurl freader.onload=e=>console.log(freader.result)// 异步的,因此须要回调里面拿
状况就是上面几种,那咱们要作的其实就是统一一下流程app
缓存了数据,而后下载缓存(由于是缓存,因此秒下)
bloburl
本地缓存下载dataurl
本地缓存下载bloburl
好一点,可是只适用于小文件。咱们让 ajax
直接返回 blob
。而后构建 bloburl
用于下载。
downloadFile2 = (url)=>{ var xhr = new XMLHttpRequest(); xhr.open('get', url); xhr.responseType='blob';//这是精髓 xhr.onprogress = onprogress2;//下载进度 // .upload.onprogress 这个是上传的时候的进度 xhr.onreadystatechange = ()=>{ if(xhr.readyState == 4 && xhr.status == 200){ nativeDownload(URL.createObjectURL(xhr.response)) } } xhr.send() }
若是是一些封装过的 ajax
,没办法使用 xhr.responseType='blob'
之类的,返回回来是字符串。那咱们须要怎么出转换呢?
blob
to *
blob
须要配合 FileReader
来读取
blob
to arrayBuffer
(readAsArrayBuffer
)
通用的、固定长度的原始二进制数据缓冲区
var fileReader = new FileReader(); fileReader.readAsArrayBuffer(xhr.response);//xhr.reponse 是 blob 类型 fileReader.onload = e=>console.log(fileReader.result);
blob
to DataURL
(readAsDataURL
)
Base64 是一组类似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成 radix-64 的表现形式后可以用 ASCII 字符串的格式表示出来。Base64 这个词出自一种 MIME 数据传输编码。 --MDN
blob
to Text
(readAsText
)blob
to BinaryString
(readAsBinaryString
)*
to blob
arrayBuffer
to blob
new Blob([arrayBuffer], {type: 'image/jpeg'})
base64
to blob
(new Uint8Array(Array.from(atob(base64url.split(',')[1])).map(v=>v.charCodeAt()))).buffer //base64url.split(',')[1] //截取不要 data:images/jpeg;base64, 这串 //atob //转换成 BinaryString //Array.from //转换成数组 //map(v=>v.charCodeAt()) //转换成对应的 ascii 码 //Uint8Array 转换成 Uint8Array 而后输出 buffer
BinaryString
to blob
BinaryString
Text
to blob
ajax
默认就是 Text
类型的返回值。这个我以为是编码类型的转换,好比 utf-8
to ascii
,目前我还没找到好的实现方法。以前就写过一篇AJAX 的进阶使用(Blob、ArrayBuffer、FormData、Document、JSON、Text),里面讲了这些支持的类型。
base64转换上传,也写过这样的。
前端目前须要操做的东西愈来愈多了。
在最上面那个问答里,有个库去实现 download 操做。实现原理能够本身去看看。