簡述
前端由於安全方面的因素,不能直接對文件進行寫操作。但是在實際的業務需求中,難免會遇到各種各樣文件的下載、預覽。
如果服務端下載文件是以流的形式傳遞到前端,前端通常是將流轉換為objectURL,借用a標簽的download屬性,進行文件下載。但是有時候會遇到下載文件處理失敗的場景,這樣服務端消息的返回格式不再是流,而是json,此時雖然前端可以正常導出文件,但是文件內容是服務端返回的消息,處置不怎么妥當,這個時候,能有讀取流的方法就好了。本文簡要概述下,前端讀取二進制流的方法。
二進制文件下載
普通的二進制文件下載:首先需要將請求頭的response-type設置為blob,其次,在接收到響應消息時,可以調用以下方法。
function download(blob) {
// 創建一個blob鏈接
let url = URL.createObjectURL(blob)
let a = document.createElement('a')
a.setAttribute('download', url)
a.href=ur;
a.style.display = 'none'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
// 每次調用URL.createObjectURL,都會創建一個新的URL對象,瀏覽器內存中會保持對該對象的引用
// 只有在document銷毀時,才會釋放此部分內存
// 在考慮性能的情況下,在url使用結束后,最好釋放此部分內存
URL.revokeObjectURL(url)
}
二進制文件讀取
上述只是二進制流文件一般的下載方式,當服務端傳回的響應類型content-type=application/json時,我們仍以二進制流的方式去解析處理,會導致導出文件內容出現問題,比如Excel中,內容為服務端響應的消息,因此,我們在處理服務器響應內容時,需要做下前置的攔截。
- 聲明一個blob變量
var debug = { hello: "world" };
var blob = new Blob([JSON.stringify(debug, null, 2)], {type : 'application/json'})
blob內容的讀取,主要有兩種方式,FileReader和Response。
FileReader
FileReader顧名思義,這個對象主要就是用來讀取文件內容,兼容性比較好,有以下幾種讀取內容格式:readAsArrayBuffer、readAsBinaryString、readAsDataURL、readdAsText。FileReader讀取方法主要如下所示:
var reader = new FileReader()
reader.addEventListener('loadend', function (e) {
// 輸出字符串 {hello: world}
console.log(e.target.result)
})
reader.readAsText(blob)
Response
Response是Fetch API的一個接口,呈現的是對一次請求數據的響應。瀏覽器兼容性比FileReader要差點,支持Chrome 42+、FireFox 39+。
Response實例化
let myResponse = new Response(body, init)
bodyBlobBufferSourceFormDataURLSearchParamsUSVString
initstatusstatusTextheaders
Response實現了body接口,所以,在實例化Response時,可以調用Body.blob()、body.formData()、body.json()、body.text()序列化返回值,返回值是一個Promise。具體實現方法如下所示:
var blobReader = new Response(blob).json()
blobReader.then(res => {
console.log(res)
})
小結
有了解析服務器返回值的方法,我們在下載文件時,就可以多判斷服務器返回值的content-type,如果返回值不是blob,我們可以做一些自定義處理。
