Vue3 + Axios + Ant Design Vue 請求封裝詳解教程(含 Token 鑒權、加密、下載)

Vue3 + Axios + Ant Design Vue 請求封裝詳解教程(含 Token 鑒權、加密、下載)


一、完整源碼(請先閱讀)

import { message, Modal } from 'ant-design-vue';
import axios from 'axios';
import { localRead } from '/@/utils/local-util';
import { useUserStore } from '/@/store/modules/system/user';
import { decryptData, encryptData } from './encrypt';
import { DATA_TYPE_ENUM } from '../constants/common-const';
import _ from 'lodash';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js';// token的消息頭
const TOKEN_HEADER = 'Authorization';// 創建axios對象
const smartAxios = axios.create({baseURL: import.meta.env.VITE_APP_API_URL,
});// 退出系統
function logout() {useUserStore().logout();location.href = '/';
}// ================================= 請求攔截器 =================================smartAxios.interceptors.request.use((config) => {// 在發送請求之前消息頭加入token tokenconst token = localRead(LocalStorageKeyConst.USER_TOKEN);if (token) {config.headers[TOKEN_HEADER] = 'Bearer ' + token;} else {delete config.headers[TOKEN_HEADER];}return config;},(error) => {// 對請求錯誤做些什么return Promise.reject(error);}
);// ================================= 響應攔截器 =================================// 添加響應攔截器
smartAxios.interceptors.response.use((response) => {// 根據content-type ,判斷是否為 json 數據let contentType = response.headers['content-type'] ? response.headers['content-type'] : response.headers['Content-Type'];if (contentType.indexOf('application/json') === -1) {return Promise.resolve(response);}// 如果是json數據if (response.data && response.data instanceof Blob) {return Promise.reject(response.data);}// 如果是加密數據if (response.data.dataType === DATA_TYPE_ENUM.ENCRYPT.value) {response.data.encryptData = response.data.data;let decryptStr = decryptData(response.data.data);if (decryptStr) {response.data.data = JSON.parse(decryptStr);}}const res = response.data;if (res.code && res.code !== 1) {// `token` 過期或者賬號已在別處登錄if (res.code === 30007 || res.code === 30008) {message.destroy();message.error('您沒有登錄,請重新登錄');setTimeout(logout, 300);return Promise.reject(response);}// 等保安全的登錄提醒if (res.code === 30010 || res.code === 30011) {Modal.error({title: '重要提醒',content: res.msg,});return Promise.reject(response);}// 長時間未操作系統,需要重新登錄if (res.code === 30012) {Modal.error({title: '重要提醒',content: res.msg,onOk: logout,});setTimeout(logout, 3000);return Promise.reject(response);}message.destroy();message.error(res.msg);return Promise.reject(response);} else {return Promise.resolve(res);}},(error) => {// 對響應錯誤做點什么if (error.message.indexOf('timeout') !== -1) {message.destroy();message.error('網絡超時');} else if (error.message === 'Network Error') {message.destroy();message.error('網絡連接錯誤');} else if (error.message.indexOf('Request') !== -1) {message.destroy();message.error('網絡發生錯誤');}return Promise.reject(error);}
);// ================================= 對外提供請求方法:通用請求,get, post, 下載download等 =================================/*** get請求*/
export const getRequest = (url, params) => {return request({ url, method: 'get', params });
};/*** 通用請求封裝* @param config*/
export const request = (config) => {return smartAxios.request(config);
};/*** post請求*/
export const postRequest = (url, data) => {return request({data,url,method: 'post',});
};// ================================= 加密 =================================/*** 加密請求參數的post請求*/
export const postEncryptRequest = (url, data) => {return request({data: { encryptData: encryptData(data) },url,method: 'post',});
};// ================================= 下載 =================================export const postDownload = function (url, data) {request({method: 'post',url,data,responseType: 'blob',}).then((data) => {handleDownloadData(data);}).catch((error) => {handleDownloadError(error);});
};/*** 文件下載*/
export const getDownload = function (url, params) {request({method: 'get',url,params,responseType: 'blob',}).then((data) => {handleDownloadData(data);}).catch((error) => {handleDownloadError(error);});
};function handleDownloadError(error) {if (error instanceof Blob) {const fileReader = new FileReader();fileReader.readAsText(error);fileReader.onload = () => {const msg = fileReader.result;const jsonMsg = JSON.parse(msg);message.destroy();message.error(jsonMsg.msg);};} else {message.destroy();message.error('網絡發生錯誤', error);}
}function handleDownloadData(response) {if (!response) {return;}// 獲取返回類型let contentType = _.isUndefined(response.headers['content-type']) ? response.headers['Content-Type'] : response.headers['content-type'];// 構建下載數據let url = window.URL.createObjectURL(new Blob([response.data], { type: contentType }));let link = document.createElement('a');link.style.display = 'none';link.href = url;// 從消息頭獲取文件名let str = _.isUndefined(response.headers['content-disposition'])? response.headers['Content-Disposition'].split(';')[1]: response.headers['content-disposition'].split(';')[1];let filename = _.isUndefined(str.split('fileName=')[1]) ? str.split('filename=')[1] : str.split('fileName=')[1];link.setAttribute('download', decodeURIComponent(filename));// 觸發點擊下載document.body.appendChild(link);link.click();// 下載完釋放document.body.removeChild(link);window.URL.revokeObjectURL(url);
}

二、源碼詳解

1. 依賴與常量

import { message, Modal } from 'ant-design-vue'; // 用于彈出消息和模態框提示
import axios from 'axios'; // axios 請求庫
import { localRead } from '/@/utils/local-util'; // 本地存儲讀取工具
import { useUserStore } from '/@/store/modules/system/user'; // 用戶狀態管理
import { decryptData, encryptData } from './encrypt'; // 加解密函數
import { DATA_TYPE_ENUM } from '../constants/common-const'; // 數據類型常量
import _ from 'lodash'; // 工具庫
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; // 本地存儲key常量const TOKEN_HEADER = 'Authorization'; // 請求頭攜帶token的鍵名

2. 創建 Axios 實例

const smartAxios = axios.create({baseURL: import.meta.env.VITE_APP_API_URL, // 基礎請求地址從環境變量讀取
});

3. 退出登錄

function logout() {useUserStore().logout(); // 調用用戶狀態登出方法location.href = '/'; // 跳轉到登錄頁或首頁
}

4. 請求攔截器

smartAxios.interceptors.request.use((config) => {const token = localRead(LocalStorageKeyConst.USER_TOKEN); // 從本地獲取tokenif (token) {config.headers[TOKEN_HEADER] = 'Bearer ' + token; // 自動添加到請求頭} else {delete config.headers[TOKEN_HEADER]; // 無token則刪除}return config;},(error) => {return Promise.reject(error); // 請求錯誤直接拋出}
);

作用:每個請求發送前自動帶上 token,方便后端身份校驗。

5. 響應攔截器

smartAxios.interceptors.response.use((response) => {// 判斷響應內容是否是 JSONlet contentType = response.headers['content-type'] || response.headers['Content-Type'];if (contentType.indexOf('application/json') === -1) {return Promise.resolve(response); // 非 JSON,直接返回原始響應}// 響應是 Blob 類型異常處理if (response.data && response.data instanceof Blob) {return Promise.reject(response.data);}// 解密處理if (response.data.dataType === DATA_TYPE_ENUM.ENCRYPT.value) {response.data.encryptData = response.data.data;let decryptStr = decryptData(response.data.data);if (decryptStr) {response.data.data = JSON.parse(decryptStr);}}const res = response.data;// 業務異常處理,code !== 1 表示失敗if (res.code && res.code !== 1) {// 令牌失效或賬號異地登錄if (res.code === 30007 || res.code === 30008) {message.destroy();message.error('您沒有登錄,請重新登錄');setTimeout(logout, 300);return Promise.reject(response);}// 安全登錄提醒if (res.code === 30010 || res.code === 30011) {Modal.error({ title: '重要提醒', content: res.msg });return Promise.reject(response);}// 長時間未操作需重新登錄if (res.code === 30012) {Modal.error({ title: '重要提醒', content: res.msg, onOk: logout });setTimeout(logout, 3000);return Promise.reject(response);}message.destroy();message.error(res.msg);return Promise.reject(response);} else {return Promise.resolve(res); // 成功返回業務數據}},(error) => {// 網絡錯誤統一提示if (error.message.includes('timeout')) {message.destroy();message.error('網絡超時');} else if (error.message === 'Network Error') {message.destroy();message.error('網絡連接錯誤');} else if (error.message.includes('Request')) {message.destroy();message.error('網絡發生錯誤');}return Promise.reject(error);}
);

作用:統一處理服務器響應,自動解密、鑒權失效跳轉、提示錯誤信息。

6. 通用請求封裝(GET,POST)

export const getRequest = (url, params) => {return request({ url, method: 'get', params });
};export const postRequest = (url, data) => {return request({ url, method: 'post', data });
};export const request = (config) => {return smartAxios.request(config);
};

統一通過 request 發起請求,方便未來統一處理或擴展。

7. 加密請求

export const postEncryptRequest = (url, data) => {return request({url,method: 'post',data: { encryptData: encryptData(data) }, // 發送加密后的數據});
};

對敏感參數統一加密,保證傳輸安全。

8. 文件下載封裝

export const postDownload = (url, data) => {request({url,method: 'post',data,responseType: 'blob',}).then(handleDownloadData).catch(handleDownloadError);
};export const getDownload = (url, params) => {request({url,method: 'get',params,responseType: 'blob',}).then(handleDownloadData).catch(handleDownloadError);
};

支持 GET/POST 下載,返回二進制流。

9. 下載結果與錯誤處理

function handleDownloadError(error) {if (error instanceof Blob) {const fileReader = new FileReader();fileReader.readAsText(error);fileReader.onload = () => {const msg = fileReader.result;const jsonMsg = JSON.parse(msg);message.destroy();message.error(jsonMsg.msg);};} else {message.destroy();message.error('網絡發生錯誤', error);}
}function handleDownloadData(response) {if (!response) return;let contentType = _.isUndefined(response.headers['content-type']) ? response.headers['Content-Type'] : response.headers['content-type'];let url = window.URL.createObjectURL(new Blob([response.data], { type: contentType }));let link = document.createElement('a');link.style.display = 'none';link.href = url;let str = _.isUndefined(response.headers['content-disposition'])? response.headers['Content-Disposition'].split(';')[1]: response.headers['content-disposition'].split(';')[1];let filename = _.isUndefined(str.split('fileName=')[1]) ? str.split('filename=')[1] : str.split('fileName=')[1];link.setAttribute('download', decodeURIComponent(filename));document.body.appendChild(link);link.click();document.body.removeChild(link);window.URL.revokeObjectURL(url);
}

處理下載文件流,自動從響應頭解析文件名并觸發瀏覽器下載。錯誤時嘗試讀取 Blob 里的錯誤信息并提示。


三、總結

  • 封裝 axios 實例方便集中管理基礎地址、攔截器、錯誤處理。
  • 請求攔截器自動附帶 token,保證鑒權。
  • 響應攔截器統一處理異常、token失效自動登出、數據加密解密。
  • 請求方法封裝標準的 getRequestpostRequest 和加密 postEncryptRequest
  • 文件下載封裝支持流下載及錯誤提示,提升用戶體驗。
  • 使用此封裝,業務代碼只需專注調用接口,提升開發效率和代碼規范。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84334.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84334.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84334.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SQL注入安全研究

?據OWASP 2023報告顯示,SQL注入連續15年位居Web安全威脅榜首,在應用漏洞中占比34.1%?? ?NIST統計顯示:2022-2023年高危SQL注入漏洞同比增長27%,企業平均修復成本達$320,000? 一、漏洞本質與技術原理解析 1. SQL注入核心機理…

Ubuntu最新版本(Ubuntu22.04LTS)安裝nfs服務器

NFS(Network File System)是一種允許不同計算機之間共享文件的網絡文件系統。 在Ubuntu 22.04 LTS中,您可以使用以下步驟安裝并配置NFS服務器。 一、安裝NFS服務器 在Ubuntu 22.04 LTS中,您可以使用以下命令安裝NFS服務器&…

學習筆記丨數字信號處理(DSP)的應用——圖像處理篇

📌 DSP在圖像處理中的應用:核心技術解析 數字信號處理(DSP)是圖像處理的核心技術之一,廣泛應用于增強、壓縮、分析和識別等領域。以下是DSP在圖像處理中的關鍵應用及技術細節: 目錄 🔍 圖像增…

Kafka Broker處理消費者請求源碼深度解析:從請求接收到數據返回

在Kafka生態體系中,消費者從Broker拉取消息是實現數據消費的關鍵環節。Broker如何高效處理消費者請求,精準定位并返回對應分區數據,直接決定了整個消息系統的性能與穩定性。接下來,我們將聚焦Kafka Broker端,深入剖析其…

Objective-C與Swift混合編程

Objective-C與Swift混合編程的基本概念 Objective-C與Swift混合編程是指在同一項目中同時使用兩種語言進行開發。這種混合編程方式在遷移舊項目或利用Swift新特性時非常有用。兩種語言可以相互調用,但需要遵循特定的規則和橋接機制。 設置混合編程環境 在Xcode項…

IDE深度集成+實時反饋:企業級軟件測試方案Parasoft如何重塑汽車巨頭的測試流程

在汽車行業數字化轉型的浪潮中,全球第四大汽車集團Stellantis曾面臨嚴峻的測試效率挑戰:開發與測試流程脫節、團隊對“測試左移”策略的抵觸、TDD(測試驅動開發)推進困難……這些痛點直接導致質量保障滯后,拖慢產品交付…

【Linux】Linux異步I/O -libaio

一、libaio 原理概述 1.1 libaio 介紹 libaio(Linux Asynchronous I/O)是 Linux 內核提供的異步 I/O 庫,其核心原理是: 異步提交:應用程序通過 io_submit 提交 I/O 請求后立即返回,不阻塞進程事件通知&a…

git submodule 和git repo介紹

這是一個 Git 子模塊(submodule)管理問題。當一個 Git 倉庫(主倉庫)中包含多個其他 Git 倉庫(子倉庫)時,最推薦的做法是使用 Git 子模塊 或 Git 子樹(subtree) 進行管理。…

識別網絡延遲與帶寬瓶頸

識別網絡延遲與帶寬瓶頸 在分布式系統與微服務架構日益普及的背景下,網絡性能成為影響系統響應速度與服務可用性的重要因素。網絡延遲和帶寬瓶頸是兩類最常見的網絡性能障礙。準確識別這兩類瓶頸,有助于系統架構師從根源優化服務質量,保障系統在高并發、高流量場景下依然具…

Linux內網穿透(frp)

目標:讓我的VMware虛擬機某個服務擁有自己的外網訪問地址 FRP 服務端(公網服務器)配置 1. 下載 FRP 登錄公網服務器,執行以下命令下載并解壓 FRP: # 下載對應版本(以Linux 64位為例) wget h…

《Vuejs設計與實現》第 9 章(簡單 diff 算法)

目錄 9.1 減少 DOM 操作的性能開銷 9.2 DOM 復用與 key 的作用 9.3 找到需要移動的元素 9.4 如何移動元素 9.5 添加新元素 9.6 移除不存在的元素 9.7 總結 當新舊 vnode 的子節點都是一組節點時,為了以最小的性能開銷完成更新操作,需要比較兩組子…

隊列,環形緩沖區實現與應用:適用于GD32串口編程或嵌入式底層驅動開發

環形緩沖區實現與應用:從基礎到實踐 在嵌入式系統和實時數據處理場景中,環形緩沖區(Circular Buffer)是一種非常常用的的數據結構,它能有效地管理數據的讀寫操作,尤其適用于數據流的臨時存儲與轉發。 今天…

WHAT - Expo Go 和 development build

文章目錄 1. 什么是 Expo Go?簡介作用限制2. 什么是 Development Build(開發構建)?簡介功能創建方式3. 它們有什么區別?總結建議怎么從 Expo Go 遷移到開發構建一、什么是“遷移”?二、遷移步驟總覽三、詳細操作步驟1. 安裝 expo-dev-client2. 配置 eas.json(Expo 應用服…

Keepalived 配置 VIP 的核心步驟

Keepalived 配置 VIP 的核心步驟主要涉及安裝軟件、主備節點配置及服務管理。以下是具體操作指南: 一、安裝 Keepalived ?Ubuntu/Debian 系統? sudo apt update sudo apt install keepalived ?CentOS/RHEL 系統? sudo yum install keepalived 注:需確保已配置 EPE…

HarmonyOS 5折疊屏自適應廣告位布局方案詳解

以下是HarmonyOS 5折疊屏廣告位自適應布局的完整技術方案,綜合響應式設計、動態交互與元服務融合策略: 一、核心布局技術? ?斷點響應式設計? 基于屏幕寬度動態調整布局結構,避免簡單拉伸: // 定義斷點閾值(單位&am…

【數據分析十:Classification prediction】分類預測

一、分類的定義 已知:一組數據(訓練集) (X, Y) 例如: x:數據特征/屬性(如收入) y:類別標記(是否有借款) 任務: 學習一個模型,利用每一條記錄…

設計模式-接口隔離原則(Interface Segregation Principle, ISP)

接口隔離原則(Interface Segregation Principle, ISP) 核心思想:客戶端不應被迫依賴它們不使用的接口方法。 目標:通過拆分臃腫的接口為更小、更具體的接口,減少不必要的依賴,提高系統的靈活性和可維護性。…

超融合:系統工程還是軟件工程? 從H3C UIS9.0看超融合的技術本質

在數字化轉型的浪潮中,超融合基礎架構(Hyper-Converged Infrastructure, HCI)憑借其簡化部署、彈性擴展和高效運維的優勢,成為企業IT基礎設施升級的重要選擇。 然而,關于超融合究竟屬于系統工程還是軟件工程的討論一直…

青少年編程與數學 01-012 通用應用軟件簡介 01 Microsoft Office辦公軟件

青少年編程與數學 01-012 通用應用軟件簡介 01 Microsoft Office辦公軟件 **一、Microsoft Office辦公軟件概述****二、發展過程**(一)早期起源(二)技術演進 **三、主要用途或功能**(一)文字處理&#xff0…

vivado IP綜合選項

在 Vivado 中,生成 IP 文件時的 Synthesis Options 提供了兩種主要的綜合模式:Global 和 Out of Context per IP。這兩種模式的主要區別如下: 1. Global Synthesis(全局綜合) 定義:在這種模式下&#xff…