一文詳解如何根據(jù)后端返回的url下載json文件
需求場景描述
有時(shí)候會遇到異步接口會返回一個(gè) url 地址,然后前端需要根據(jù)這個(gè) url 地址去下載文件資源的需求場景。 而這個(gè) url 其實(shí)是一個(gè)靜態(tài)資源地址,并非一個(gè)經(jīng)過后端接口內(nèi)部處理的接口地址。 所以當(dāng)嘗試像下面這樣使用 a 標(biāo)簽去執(zhí)行該 url 地址,會發(fā)現(xiàn)它是直接預(yù)覽打開的一個(gè) json 文件(也可能是一個(gè)txt,js等文件)
<a href=" http://192.168.0.172:8888/file/package.json" rel="external nofollow" download="package.json">下載json</a>
在瀏覽器窗口直接打開該 url ,會發(fā)現(xiàn)它也是直接打開了這個(gè) json 文件。txt,js,css 等可訪問的靜態(tài)資源地址也會被直接打開(這或許叫預(yù)覽,兩種形式,一種是預(yù)覽文件,另一種是下載文件)而不是下載。 這和資源地址返回的方式(responseType)有關(guān), 默認(rèn)返回的可能是字節(jié)流或字符流的形式,而這種返回形式能被瀏覽器識別預(yù)覽,于是就直接打開了(執(zhí)行了預(yù)覽文件模式)。 我們更常見的可能是圖片,它可以直接在瀏覽器打開預(yù)覽,這大概率也是因?yàn)槠浞祷氐男问绞?base64 的圖片, 它能被瀏覽器識別,于是就瀏覽器就正常執(zhí)行了文件預(yù)覽模式,而非下載模式。
例如,同樣位置的靜態(tài)資源,一個(gè)是 json,一個(gè)是 .zip 壓縮文件。兩個(gè) url,你會發(fā)現(xiàn)在瀏覽器窗口執(zhí)行 json 文件的 url, 瀏覽器執(zhí)行的是預(yù)覽模式,直接打開了文件。而在瀏覽器窗口輸入 .zip 壓縮文件的 url,瀏覽器并沒有執(zhí)行預(yù)覽模式, 而是執(zhí)行了下載模式,直接下載文件了。
下面是兩個(gè)測試的示意圖
那么,如果想根據(jù)這種接口返回的 url(一個(gè)靜態(tài)資源地址,例如 一個(gè) json 或 txt 文件的資源地址), 直接下載而不是預(yù)覽該如何做呢?
處理方案關(guān)鍵詞:異步下載,設(shè)置 responseType = 'blob'。
實(shí)現(xiàn)思路分析
1.設(shè)置請求的返回方式為 responseType = 'blob',如果不設(shè)置可能會導(dǎo)致下載后無法正常打開。
2.設(shè)置請求地址,請求方式,以及必要的請求頭參數(shù)等,例如 token 等,可按需設(shè)置。
3.將返回的字節(jié)流(字符流)轉(zhuǎn)換為 blob 對象
const blob = new Blob([res.data]) // 將字節(jié)流(字符流)轉(zhuǎn)換為 blob 對象
4.為該 blob 在創(chuàng)建一個(gè)資源 url
let url = window.URL.createObjectURL(blob)
5.使用該 url 創(chuàng)建一個(gè) a 標(biāo)簽,模擬點(diǎn)擊事件執(zhí)行下載
這一步,和我們平常使用的同步下載資源文件方式一致。下載后需注意釋放掉 blob 對象的 ObjectURL。
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) 解決這個(gè)問題。
// 解決 ie 不支持下載 blob資源 if ('msSaveOrOpenBlob' in navigator) { window.navigator.msSaveOrOpenBlob(blob, filename) return }
上述代碼在 ie 執(zhí)行會自動打開一個(gè)詢問窗口,該窗口會問你是下載還是預(yù)覽,選擇下載就可以正常下載了。
下面是一個(gè)在 ie 執(zhí)行下載 blob 后的截圖
完整的 demo 示例
<template> <div> <h1 @click="xhrDownload"> xhr 異步下載 json 等資源文件</h1> <h1 @click="axiosDownload">axios 異步下載 json 等資源文件</h1> </div> </template> <script> import axios from 'axios' export default { name: 'DownloadFile', methods: { axiosDownload () { // config 是配置對象,可按需設(shè)置,例如 responseType,headers 中設(shè)置 token 等 const config = {} // 這一步可能很關(guān)鍵,特別是在能下載,但是下載下來打開異常的時(shí)候。 config.responseType = 'blob' axios.get('http://localhost:8278/package.json', config).then(res => { const blob = new Blob([res.data]) // 將字節(jié)流(字符流)轉(zhuǎn)換為 blob 對象 this.blobDownload(blob) }) }, /** * 下載文件:下載 blob 對象形式的文件 * @param blob * @param filename */ blobDownload (blob, filename = '文件.json') { let url = window.URL.createObjectURL(blob) // 解決 ie 不支持下載 blob資源 if ('msSaveOrOpenBlob' in navigator) { window.navigator.msSaveOrOpenBlob(blob, filename) return } 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對象 }, xhrDownload (params) { // token 等header 參數(shù)和 請求方式都可以按需配置 const token = localStorage.getItem('token') || '' const url = 'http://localhost:8278/package.json' let xhr = new XMLHttpRequest() // get 方式 xhr.open('get', url + '?timeStamp=' + new Date().getTime(), true) xhr.setRequestHeader('Cache-Control', 'no-cache') xhr.setRequestHeader('Content-type', 'application/json') // xhr.setRequestHeader('kms-token', token) // 返回類型blob,不設(shè)置會打不開 excel xhr.responseType = 'blob' // 定義請求完成的處理函數(shù),請求前也可以增加加載框/禁用下載按鈕邏輯 xhr.onload = function () { // 請求完成 if (this.status === 200) { let blob = this.response let url = window.URL.createObjectURL(blob) // 生成 url,創(chuàng)建一個(gè)a標(biāo)簽用于下載 let a = document.createElement('a') a.download = '收支清單.json' a.href = url a.click() } } xhr.send(JSON.stringify(params)) } } } </script>
總結(jié)
到此這篇關(guān)于如何根據(jù)后端返回的url下載json文件的文章就介紹到這了,更多相關(guān)后端返回url下載json文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js 獲取、清空input type="file"的值(示例代碼)
本篇文章主要介紹了js 獲取、清空input type="file"的值(示例代碼) 需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12js實(shí)現(xiàn)點(diǎn)擊切換checkbox背景圖片的簡單實(shí)例
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)點(diǎn)擊切換checkbox背景圖片的簡單實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05in.js 一個(gè)輕量級的JavaScript顆?;K加載和依賴關(guān)系管理解決方案
近一年來,國內(nèi)外都十分熱衷于異步加載的研究,為了加快頁面的載入速度,無阻塞加載Javascript的方法和框架成為了前端開發(fā)的焦點(diǎn)和亮點(diǎn)之一。2011-07-07layui從數(shù)據(jù)庫中獲取復(fù)選框的值并默認(rèn)選中方法
今天小編就為大家分享一篇layui從數(shù)據(jù)庫中獲取復(fù)選框的值并默認(rèn)選中方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08JS實(shí)現(xiàn)靈巧的下拉導(dǎo)航效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)靈巧的下拉導(dǎo)航效果代碼,通過自定義js插件腳本dropdown.js實(shí)現(xiàn)簡單的下拉導(dǎo)航效果的功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08js控制文本框只能輸入中文、英文、數(shù)字與指定特殊符號的實(shí)現(xiàn)代碼
下面小編就為大家?guī)硪黄猨s控制文本框只能輸入中文、英文、數(shù)字與指定特殊符號的實(shí)現(xiàn)代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09Bootstrap警告(Alerts)的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了Bootstrap警告(Alerts)的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03