如何用ajax下載文件
引子
在HTML5沒來之前,瀏覽器想要下載文件,可能有這麽幾種方式:
借助a標簽,
<a href="學習資料.xlsx"></a>
window.location = ‘學習資料.xlsx‘
借助瀏覽器插件,如flash等(沒考證過)
除了第三外,前兩種方法有個缺點,就是無法知道下載是否完成,因為瀏覽器沒有給出相關的事件。但是,自從有了Blob,fetch, xhr2這些好用的API之後,ajax下載文件(小文件)就變得可行了,核心原因就在於Blob和ArrayBuffter這些API提供給了瀏覽器操作二進制文件的能力。接下來就開始我的表演
1. fetch方法
fetch優點有很多,比如基於promise,寫起來直觀易懂,缺點是IE,包括IE11全部不支持。
使用時要註意一點是,fetch請求時默認不會帶上cookie,如果你的api是在登錄後才能訪問,記得手動設置 credentials選項。下面是下載一個文件的代碼:
fetch(‘學習資料.xlsx‘, {
method: ‘GET‘,
credentials: "same-origin"// 帶上cookie
})
.then(res => res.blob())
.then(blob => {
saveAs(blob) //fileSaver.js中的方法
})
從上面可以看出,調用fetch時會返回一個promise,當promise resolve時,會傳出一個Response的實例(res),這個res除了有status
, statusText
ok
這幾個屬性用於獲取服務器相應的狀態值外,還有幾個炫酷的方法,正式這幾個方法,使瀏覽器可以請求的數據類型不再局限於文本,他們是:
res.blob() //返回值是一個promise,promise resolve後會拿到一個blob對象 res.json() //返回值是一個promise,promise resolve後會拿到一個json對象,無需再調用JSON.parse res.text() //返回值是一個promise,promise resolve後會拿到一個字符串 res.formData() //返回值是一個promise,promise resolve後會拿到一個表單數據對象(formData)
所以拿到blob後,接下來就是觸發瀏覽器的下載了,這裏調用了一個saveAs函數,它來自FileSaver.js,一個不用請求api也可以觸發瀏覽器下載動作的庫,它接受一個blob對象,和一個可選的文件名稱參數,就能觸發下載動作。
2.xhr2方法
xhr2的兼容性比fetchAPI要好,兼容到IE10,它沒有向fetch一樣把難用的xhr推翻重做,而是做了一些有用的擴展,比如xhr.responseType
,在發起請求前,通過設置這個屬性,可以使瀏覽器對返回的數據進行處理,就像res的那些有用的方法一樣。xhr.responseType可以取下列值:
"arraybuffer",
"blob",
"document",
"json",
"text"
沒錯,就是和上面的res的那些方法殊途同歸。當請求數據返回時,你可以從xhr.response
拿到相應的數據。為什麽不是res.responseText
呢?很明顯這是xhr1時期的,從這個屬性只能拿到字符串,是滿足不了我們的需求的。
接下來的事情就跟上面一樣了,照例貼一下代碼:
var xhr = new XMLHttpRequest();
xhr.responseType = ‘blob‘;
xhr.open(‘GET‘, url, true);
xhr.onload = function(){
var res = xhr.response;
if(res){
saveAs(res, filename);
}
}
xhr.send();
到這裏,你就可以從容掌握文件下載的狀態了。最後再啰嗦一句,xhr.onload也是xhr2增加的事件,有了它,再也不想用xhr.onReadyStateChange了。其他新增的事件還有‘onprocess‘, ‘onerror‘, ‘onabort‘, ‘onloadstart‘,‘onloadend‘, ‘ontimeout‘。(完)
如何用ajax下載文件