如何根據後端返回的url下載json文件

語言: CN / TW / HK

theme: github highlight: a11y-dark


本文已參與「新人創作禮」活動,一起開啟掘金創作之路。

如何根據後端返回的url下載json文件

好文推薦:

約2萬字-Vue源碼解讀彙總篇(續更)

前端要會打組合拳,覆盤30+技術點打出的功能

需求場景描述

有時候會遇到異步接口會返回一個 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,瀏覽器並沒有執行預覽模式, 而是執行了下載模式,直接下載文件了。

下面是兩個測試的示意圖

image.png

image.png

那麼,如果想根據這種接口返回的 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 後的截圖

image.png

完整的 demo 示例

```html

```