如何根據後端返回的url下載json檔案
theme: github highlight: a11y-dark
本文已參與「新人創作禮」活動,一起開啟掘金創作之路。
如何根據後端返回的url下載json檔案
好文推薦:
需求場景描述
有時候會遇到非同步介面會返回一個 url 地址,然後前端需要根據這個 url 地址去下載檔案資源的需求場景。 而這個 url 其實是一個靜態資源地址,並非一個經過後端介面內部處理的介面地址。 所以當嘗試像下面這樣使用 a 標籤去執行該 url 地址,會發現它是直接預覽開啟的一個 json 檔案(也可能是一個txt,js等檔案)
html
<a href=" http://192.168.0.172:8888/file/package.json" download="package.json">下載json</a>
在瀏覽器視窗直接開啟該 url ,會發現它也是直接打開了這個 json 檔案。txt,js,css 等可訪問的靜態資源地址也會被直接開啟(這或許叫預覽,兩種形式,一種是預覽檔案,另一種是下載檔案)而不是下載。 這和資源地址返回的方式(responseType)有關, 預設返回的可能是位元組流或字元流的形式,而這種返回形式能被瀏覽器識別預覽,於是就直接打開了(執行了預覽檔案模式)。 我們更常見的可能是圖片,它可以直接在瀏覽器開啟預覽,這大概率也是因為其返回的形式是 base64 的圖片, 它能被瀏覽器識別,於是就瀏覽器就正常執行了檔案預覽模式,而非下載模式。
例如,同樣位置的靜態資源,一個是 json,一個是 .zip 壓縮檔案。兩個 url,你會發現在瀏覽器視窗執行 json 檔案的 url, 瀏覽器執行的是預覽模式,直接打開了檔案。而在瀏覽器視窗輸入 .zip 壓縮檔案的 url,瀏覽器並沒有執行預覽模式, 而是執行了下載模式,直接下載檔案了。
下面是兩個測試的示意圖
那麼,如果想根據這種介面返回的 url(一個靜態資源地址,例如 一個 json 或 txt 檔案的資源地址), 直接下載而不是預覽該如何做呢?
處理方案關鍵詞:非同步下載,設定 responseType = 'blob'。
實現思路分析
1.設定請求的返回方式為 responseType = 'blob',如果不設定可能會導致下載後無法正常開啟。
2.設定請求地址,請求方式,以及必要的請求頭引數等,例如 token 等,可按需設定。
3.將返回的位元組流(字元流)轉換為 blob 物件
js
const blob = new Blob([res.data]) // 將位元組流(字元流)轉換為 blob 物件
4.為該 blob 在建立一個資源 url
js
let url = window.URL.createObjectURL(blob)
5.使用該 url 建立一個 a 標籤,模擬點選事件執行下載
這一步,和我們平常使用的同步下載資原始檔方式一致。下載後需注意釋放掉 blob 物件的 ObjectURL。
js
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = filename
document.body.appendChild(link)
link.click()
document.body.removeChild(link) // 下載完成移除元素
window.URL.revokeObjectURL(url) // 釋放掉blob物件
tips:ie 並不支援直接下載 blob 資源,可以利用 window.navigator.msSaveOrOpenBlob(blob, filename) 解決這個問題。
js
// 解決 ie 不支援下載 blob資源
if ('msSaveOrOpenBlob' in navigator) {
window.navigator.msSaveOrOpenBlob(blob, filename)
return
}
上述程式碼在 ie 執行會自動開啟一個詢問視窗,該視窗會問你是下載還是預覽,選擇下載就可以正常下載了。
下面是一個在 ie 執行下載 blob 後的截圖
完整的 demo 示例
```html
```
- 雙18期|CSS揭祕之簡寫屬性
- 扁平資料轉tree與tree資料扁平化
- CSS揭祕之效能優化技巧篇
- 資料視覺化:核心、互動、分類與工具
- 哇,這個易用工具適合我這水平的人
- 前端技術圖譜:看看你學廢了哪些?
- 雙17期|跨域資源共享:跨域錯誤該前端還是後端處理?
- js對話資料庫體驗:hello-mysql
- CSS揭祕之控制繼承:height能變為可繼承嗎?
- 進階|監控上傳和下載進度
- 今日軟考|普通程式設計師或許更應考軟考
- 一字一圖,領略瀏覽器方向的優化
- 天天用可替換元素(replaced element),竟說不知道
- 不要再濫用css樣式!important規則了
- 適合非大廠的70 面試題(2022-5)
- 11種樣式選擇器與樣式優先順序計算
- 面試|變數提升與函式提升,挑戰下這幾個例子?
- 雙10期|基本物件Error及8種錯誤型別
- 社群資料說話,真的是前端最卷?
- 面不面試都要會的繼承與原型鏈:原型鏈的盡頭是null?