前端最基礎的就是 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 操做。實現原理能夠本身去看看。