對於如何實現文件下載功能,根據實現的技術方式分為兩大類:
- 結合后端實現
- 純前端實現
結合后端實現
兩種實現方式
第一種、直接下載服務器的靜態資源
對於這種方式,最簡單的是使用a標簽
<a href="URL"></a>
其他的方法如form、iframe、location.href、window.open(),這里就不細講了。
第二種、前端傳參,后端生成文件
實現思路:
1、前端通過發送數據或參數給到后端
2、在由后端根據接收的數據生成文件或根據參數查找出對應的數據在生成文件
3、然后在響應請求頭中設置
Content-disposition:attachment;filename="fliename.fileType"
用於指定文件類型、文件名和文件編碼等
Content-disposition(內容-部署)是MIME協議類型的擴展,MIME協議指示MIME用戶代理如何顯示附加的文件。
4、瀏覽器接收到響應頭后就會觸發下載行為。
優缺點
優點
可以根據參數生成不同的文件,靈活性高
能實現大數據量或大文件的下載
缺點
如果需要下載的是用戶生成的內容(在線作圖等)或者內容已經全部返回到客戶端,會造成資源和帶寬的浪費
純前端實現
純前端實現並不是一定不需要后端,只是有時候后端的數據已經給到前端,用戶下載的文件內容只需要現有的數據,這時候就可以是使用純前端實現下載文件的功能來減小服務器資源和帶寬的浪費。
數據來源
1、后端返回
2、用戶輸入:在線作圖、在線表格輸入
實現思路
分為兩步:
第一步、將數據生成對應得data:URLs或blob:URLs
第二步、處理下載(或叫導出)方式
第一步、將數據生成對應得data:URLs或blob:URL
生成data:URLs
data: URLs是前綴為data:的 URL 字符串,格式為
data:[<mediatype>][;base64],<data>
mediatype 是個 MIME 類型的字符串,例如 "image/jpeg" 表示 JPEG 圖像文件。
如果被省略,則默認值為 text/plain;charset=US-ASCII
如何將數據轉換為data:URLs
第一種、對於文本類型,可以直接將數據拼接
示例
const dataURL = `data:text/plain;base64,` + textData
第二種、通過window.btoa()方法
btoa()函數將二進制數據的“字符串”創建base-64編碼的ASCII字符串。
示例
let str = new Blob(['some thing']) console.log(btoa(str)) // W29iamVjdCBCbG9iXQ== let dataURL = 'data:text/plain;base64,' + btoa(str) // data:text/plain;base64,W29iamVjdCBCbG9iXQ==
第三種、通過FileReader.readAsDataURL(blob)方法
對於File或Blob對象,可以使用FileReader.readAsDataURL()的方法轉換為data:URLs
示例
const blob = new Blob(['some thing']) const reader = new FileReader() reader.onloadend = function() { const dataUrl = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;') } reader.readAsDataURL(blob)
生成BlobURLs
blob: URLs是URL.createObjectURL() 靜態方法創建的一個 DOMString,其中包含一個表示參數中給出的對象的URL。
URL.createObjectURL()方法只能處理File或Blob對象,所以如果要生成blobURLs則必須將數據轉換為blob對象或file對象。
示例
如果數據不是File或Blob對象
const blob = new Blob([data][, MIMEType])
生成BlobURLs
const BlobURL = URL.createObjectURL(blob)
創建出來的BlobURLs需要手動調用URL.revokeObjectURL()銷毀,否則會一直保留到頁面關閉,為了獲得最佳性能和內存使用狀況,你應該在安全的時機主動釋放掉它們。
第二步、處理下載(或叫導出)方式
第一種、<a>標簽的download和href
其中<a>標簽的download是HTML5標准新增的屬性,作用是指示瀏覽器下載URL而不是導航到URL,因此將提示用戶將其保存為本地文件。另外,download屬性的值可以指定下載文件的名稱。
href則支持dataURLs和blobURLs兩種類型的值。
示例
<a download="filename" href="dataURLs或BlobURLs"></a>
第二種、location.href或window.open()
這個方法是直接把 DataURLs 或者 BlobURLs 傳到瀏覽器地址中觸發下載。有兩種方式:
window.location.href = urls; // 本窗口打開下載 window.open(urls, '_blank'); // 新開窗口下載
第三種、msSaveOrOpenBlob(IE10+)
這是 IE 特有的方法。
navigator.msSaveOrOpenBlob(blob, fileName);
第四種、iframe(IE <= 9)
其他更現代的瀏覽器也支持此方法,不過此方法效率和安全性較低,所以一般只在 IE <= 9 時使用。
var frame = document.createElement("iframe"); if ( frame ) { document.body.appendChild(frame); frame.setAttribute("style", "display:none"); frame.contentDocument.open("txt/html", "replace"); frame.contentDocument.write(data); // data 是 string 類型 frame.contentDocument.close(); frame.focus(); frame.contentDocument.execCommand("SaveAs", true, filename); document.body.removeChild(frame); }
優缺點
優點
減少服務器資源和帶寬
只需要前端,增加了前端的可控性
缺點
對於大數據量支持度不好
有兼容性問題