鴻蒙HarmonyOS中Axios網絡庫封裝與文件上傳功能實現

在開發鴻蒙HarmonyOS應用時,網絡請求功能是必不可少的。axios是一個非常流行的基于Promise的HTTP客戶端,適用于瀏覽器和Node.js環境。本文將介紹如何在鴻蒙HarmonyOS中封裝axios庫,使其能夠支持文件上傳,并提供額外的配置選項以滿足不同的業務需求。

封裝目的

  • 簡化網絡請求:通過封裝,我們可以將常用的HTTP請求操作(如GET、POST等)封裝成簡潔易用的方法。
  • 統一錯誤處理:封裝后的庫可以統一處理HTTP請求中的錯誤,提供更友好的錯誤提示和處理邏輯。
  • 支持文件上傳:提供對文件上傳的支持,包括單個文件和多個文件的上傳。

使用的庫

axios:一個流行的JavaScript庫,用于處理HTTP請求。

封裝實現

以下是封裝后的AxiosHttpRequest類的實現,支持文件上傳:

/*** author:csdn貓哥* qq:534117529* blog:https://blog.csdn.net/yyz_1987*/
//axiosHttp.etsimport axios, {AxiosError,AxiosInstance,AxiosHeaders,AxiosRequestHeaders,AxiosResponse,FormData,AxiosProgressEvent,InternalAxiosRequestConfig
} from "@ohos/axios";interface HttpResponse<T>{data: T;status: number;statusText: string;config: HttpRequestConfig;
}
export type HttpPromise<T> = Promise<HttpResponse<T>>;// 鴻蒙ArkTS文件上傳相關接口定義
/**
上傳類型支持uri和ArrayBuffer,
uri支持“internal”協議類型和沙箱路徑。
"internal://cache/"為必填字段,示例: internal://cache/path/to/file.txt;
沙箱路徑示例:cacheDir + '/hello.txt'*/
export interface UploadFile {buffer?: ArrayBuffer;fileName?: string;mimeType?: string;uri?:string;
}export interface FileUploadConfig extends HttpRequestConfig {file?: UploadFile | UploadFile[];fileFieldName?: string; // 文件字段名,默認為 'file'additionalData?: Record<string, any>; // 額外的表單數據onUploadProgress?: (progressEvent: any) => void; // 上傳進度回調
}export interface FileInfo {name: string;size: number;type: string;
}
/*** 封裝后,不支持傳入攔截器* 需要自己定義接口繼承 AxiosRequestConfig類型* 從而支持傳入攔截器,但攔截器選項應為可選屬性* 之后請求實例傳入的options為繼承了AxiosRequestConfig的自定義類型*/
interface InterceptorHooks {requestInterceptor?: (config: HttpRequestConfig) => Promise<HttpRequestConfig>;requestInterceptorCatch?: (error: any) => any;responseInterceptor?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>;responseInterceptorCatch?: (error: any) => any;
}// @ts-ignore
interface HttpRequestConfig extends InternalAxiosRequestConfig {showLoading?: boolean; //是否展示請求loadingcheckResultCode?: boolean; //是否檢驗響應結果碼checkLoginState?: boolean; //校驗用戶登陸狀態needJumpToLogin?: boolean; //是否需要跳轉到登陸頁面interceptorHooks?: InterceptorHooks;//攔截器headers?: AxiosRequestHeaders;errorHandler?: (error: any) => void; //錯誤處理
}/*** 網絡請求構造* 基于axios框架實現*/
export class AxiosHttpRequest {config: HttpRequestConfig;interceptorHooks?: InterceptorHooks;instance: AxiosInstance;constructor(options: HttpRequestConfig) {this.config = options;this.interceptorHooks = options.interceptorHooks;this.instance = axios.create(options);this.setupInterceptor()}setupInterceptor(): void {this.instance.interceptors.request.use(// 這里主要是高版本的axios中設置攔截器的時候里面的Config屬性必須是InternalAxiosRequestConfig,// 但是InternalAxiosRequestConfig里面的headers是必傳,所以在實現的子類我設置成非必傳會報錯,加了個忽略注解// @ts-ignorethis.interceptorHooks?.requestInterceptor,this.interceptorHooks?.requestInterceptorCatch,);this.instance.interceptors.response.use(this.interceptorHooks?.responseInterceptor,this.interceptorHooks?.responseInterceptorCatch,);}// 類型參數的作用,T決定AxiosResponse實例中data的類型request<T = any>(config: HttpRequestConfig): HttpPromise<T> {return new Promise<HttpResponse<T>>((resolve, reject) => {this.instance.request<any, HttpResponse<T>>(config).then(res => {resolve(res);}).catch((err) => {// 使用傳入的 errorHandler 處理錯誤const errorHandler = config.errorHandler || errorHandlerDefault;errorHandler(err); if (err) {reject(err);}});});}get<T = any>(config: HttpRequestConfig): HttpPromise<T> {return this.request({ ...config, method: 'GET' });}post<T = any>(config: HttpRequestConfig): HttpPromise<T> {return this.request({ ...config, method: 'POST' });}delete<T = any>(config: HttpRequestConfig): HttpPromise<T> {return this.request({ ...config, method: 'DELETE' });}patch<T = any>(config: HttpRequestConfig): HttpPromise<T> {return this.request({ ...config, method: 'PATCH' });}/*** 上傳單個文件或多個文件* @param config 文件上傳配置* @returns Promise<HttpResponse<T>>*/uploadFile<T = any>(config: FileUploadConfig): HttpPromise<T> {return new Promise<HttpResponse<T>>((resolve, reject) => {if (!config.file) {reject(new Error('文件不能為空'));return;}const formData = new FormData();const fileFieldName = config.fileFieldName || 'file';// 處理單個或多個文件const files = Array.isArray(config.file) ? config.file : [config.file];files.forEach((file, index) => {const fieldName = Array.isArray(config.file) ? `${fileFieldName}[${index}]` : fileFieldName;// 鴻蒙ArkTS FormData.append 支持第三個參數設置文件名和類型if (file.mimeType) {formData.append(fieldName, file.buffer, {filename: file.fileName,type: file.mimeType});} else if (file.buffer){formData.append(fieldName, file.buffer, {filename: file.fileName});}else if (file.uri){formData.append(fieldName, file.uri);}});// 添加額外的表單數據if (config.additionalData) {Object.keys(config.additionalData).forEach(key => {formData.append(key, config.additionalData![key]);});}const uploadConfig: HttpRequestConfig = {...config,method: 'POST',data: formData,headers: new AxiosHeaders({...config.headers,'Content-Type': 'multipart/form-data'})};// 添加上傳進度監聽if (config.onUploadProgress) {uploadConfig.onUploadProgress = config.onUploadProgress;}this.request<T>(uploadConfig).then(resolve).catch(reject);});}/*** 上傳多個文件* @param config 文件上傳配置* @returns Promise<HttpResponse<T>>*/uploadFiles<T = any>(config: FileUploadConfig): HttpPromise<T> {if (!Array.isArray(config.file)) {return Promise.reject(new Error('uploadFiles方法需要傳入文件數組'));}return this.uploadFile<T>(config);}/*** 獲取文件信息* @param file 文件對象* @returns FileInfo*/getFileInfo(file: UploadFile): FileInfo {return {name: file.fileName,size: file.buffer.byteLength,type: file.mimeType || 'application/octet-stream'};}/*** 驗證文件類型* @param file 文件對象* @param allowedTypes 允許的文件類型數組* @returns boolean*/validateFileType(file: UploadFile, allowedTypes: string[]): boolean {const fileType = file.mimeType || 'application/octet-stream';return allowedTypes.includes(fileType);}/*** 驗證文件大小* @param file 文件對象* @param maxSize 最大文件大小(字節)* @returns boolean*/validateFileSize(file: UploadFile, maxSize: number): boolean {return file.buffer.byteLength <= maxSize;}/*** 創建文件上傳配置* @param url 上傳地址* @param file 文件對象* @param options 其他配置選項* @returns FileUploadConfig*/createUploadConfig(url: string,file: UploadFile | UploadFile[],options: Partial<FileUploadConfig> = {}): FileUploadConfig {return {url,file,fileFieldName: 'file',...options};}
}function errorHandlerDefault(error: any) {if (error instanceof AxiosError) {//showToast(error.message)} else if (error != undefined && error.response != undefined && error.response.status) {switch (error.response.status) {// 401: 未登錄// 未登錄則跳轉登錄頁面,并攜帶當前頁面的路徑// 在登錄成功后返回當前頁面,這一步需要在登錄頁操作。case 401:break;// 403 token過期// 登錄過期對用戶進行提示// 清除本地token和清空vuex中token對象// 跳轉登錄頁面case 403://showToast("登錄過期,請重新登錄")// 清除token// localStorage.removeItem('token');break;// 404請求不存在case 404://showToast("網絡請求不存在")break;// 其他錯誤,直接拋出錯誤提示default://showToast(error.response.data.message)}}
}
export{AxiosRequestHeaders,AxiosError,AxiosHeaders,AxiosProgressEvent,FormData};
export default AxiosHttpRequest;

使用舉例

import fs from '@ohos.file.fs';
import { axiosClient, FileUploadConfig, HttpPromise, UploadFile } from '../../utils/axiosClient';
import { AxiosProgressEvent } from '@nutpi/axios';async function uploadSingleFile() {try {// 創建測試文件并讀取為ArrayBufferlet context = getContext() as common.UIAbilityContext;const cacheDir = context.cacheDir;const path = cacheDir + '/test.jpg';// 寫入測試文件const file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);fs.writeSync(file.fd, "這是一個測試文件內容");fs.fsyncSync(file.fd);fs.closeSync(file.fd);// 讀取文件為ArrayBufferconst file2 = fs.openSync(path, 0o2);const stat = fs.lstatSync(path);const buffer = new ArrayBuffer(stat.size);fs.readSync(file2.fd, buffer);fs.fsyncSync(file2.fd);fs.closeSync(file2.fd);const uploadFile:UploadFile = {fileName: 'test.jpg',mimeType: 'text/plain',uri:path};const config:FileUploadConfig = axiosClient.createUploadConfig('upload/image',uploadFile,{context:getContext(),onUploadProgress: (progressEvent:AxiosProgressEvent) => {const percentCompleted = Math.round((progressEvent.loaded * 100) / (progressEvent?.total ?? 1));console.log(`上傳進度: ${percentCompleted}%`);}});axiosClient.uploadFile<string>(config).then((res) => {//Log.debug(res.data.code)console.log('文件上傳成功:');}).catch((err:BusinessError) => {Log.debug("request","err.code:%d",err.code)Log.debug("request",err.message)console.error('文件上傳失敗:', err);});} catch (error) {}
}

核心功能解析

1. 文件上傳接口

  • UploadFile接口:定義了文件上傳的數據結構,支持uriArrayBuffer兩種方式。
  • FileUploadConfig接口:繼承自HttpRequestConfig,增加了對文件和額外表單數據的支持。
  • uploadFile方法:實現文件上傳邏輯,支持單個文件和多個文件的上傳。
  • uploadFiles方法:專門用于上傳文件數組。

2. 文件信息處理

  • getFileInfo方法:獲取文件的名稱、大小和類型。
  • validateFileType方法:驗證文件類型是否在允許的類型列表中。
  • validateFileSize方法:驗證文件大小是否超過指定的最大值。

3. 請求攔截器與響應攔截器

  • setupInterceptor方法:設置請求和響應攔截器,以便在請求發送前和響應返回后執行自定義邏輯。

4. 統一錯誤處理

  • errorHandlerDefault函數:定義了默認的錯誤處理邏輯。根據響應的狀態碼提供不同的錯誤提示。

使用示例

const httpRequest = new AxiosHttpRequest({baseURL: 'https://example.com/api',interceptorHooks: {requestInterceptor: (config) => {console.log('Request Interceptor:', config);return config;},responseInterceptor: (response) => {console.log('Response Interceptor:', response);return response;},},errorHandler: (error) => {console.error('Custom Error Handler:', error);}
});const file: UploadFile = {buffer: new ArrayBuffer(1024),fileName: 'example.txt',mimeType: 'text/plain'
};const config = httpRequest.createUploadConfig('https://example.com/api/upload', file, {additionalData: { description: '這是一個示例文件' },onUploadProgress: (progress) => {console.log('上傳進度:', progress);}
});httpRequest.uploadFile(config).then((response) => {console.log('上傳成功:', response);
}).catch((error) => {console.error('上傳失敗:', error);
});

總結

通過封裝axios庫,我們可以在鴻蒙HarmonyOS中更方便地實現網絡請求和文件上傳功能。封裝后的庫提供了統一的錯誤處理機制和豐富的配置選項,使得我們的網絡請求更加高效和靈活。希望本文能幫助大家更好地理解和使用封裝后的axios庫。

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

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

相關文章

【AI】從零開始的文本分類模型實戰:從數據到部署的全流程指南

目錄 引言 一、項目背景與目標 二、環境準備 三、數據獲取與探索 3.1 數據獲取 3.2 數據探索 四、數據預處理 4.1 文本清洗 4.2 分詞 4.3 標簽編碼 4.4 數據集劃分 4.5 特征提取 五、模型構建與訓練 5.1 邏輯回歸模型 5.2 LSTM 模型 六、模型評估 6.1 邏輯回歸…

Rust學習心得---特征對象和泛型區別

區別特性泛型&#xff08;靜態分發&#xff09;特征對象&#xff08;動態分發&#xff09;決策時機編譯時單態化&#xff08;生成具體類型的代碼&#xff09;運行時通過vtable查找方法運行性能零運行時開銷&#xff08;直接內聯調用&#xff09;有額外開銷&#xff08;指針跳轉…

ESP32-menuconfig(2) -- Application manager

按順序來說&#xff0c;第二篇本來應該是Security features&#xff0c;但是這塊內容應該到小批量才用的到&#xff0c;而一些愛好者可能永遠都不會修改這塊&#xff0c;所以先看看更常用Application manager&#xff0c;這部分內容也比較少。 Application managerCONFIG_APP_C…

ArgoCD 與 GitOps:K8S 原生持續部署的實操指南

容器技術的爆發讓 Kubernetes&#xff08;K8s&#xff09;成為了「云原生時代的操作系統」—— 它能高效編排成千上萬的容器&#xff0c;解決彈性伸縮、資源調度等核心問題。但隨著企業應用規模擴大&#xff0c;K8s 的「部署與管理」逐漸暴露新的挑戰&#xff1a; 多環境&…

Day36--動態規劃--1049. 最后一塊石頭的重量 II,494. 目標和,474. 一和零

Day36–動態規劃–1049. 最后一塊石頭的重量 II&#xff0c;494. 目標和&#xff0c;474. 一和零 遇到難題&#xff0c;思考超過20分鐘沒有思路的&#xff0c;要跳過&#xff01;不然時間效率太低了。 **看題解同理&#xff0c;看20分鐘看不懂的&#xff0c;也要跳過&#xff0…

前端開發技術深度總結報告

前端開發技術深度總結報告 &#x1f4cb; 項目背景 基于 Vue 3 TypeScript Element Plus 的企業級產品管理系統&#xff0c;重點解決產品表單的數據緩存、頁面導航、用戶體驗等核心問題。&#xfffd;&#xfffd; 遇到的問題及解決方案 1. 瀏覽器控制臺錯誤處理 問題: 大量第…

Linux 單機部署 Kafka 詳細教程(CentOS 7+)

系列博客專欄&#xff1a; SpringBoot與微服務實踐系列博客Java互聯網高級培訓教程 一、環境準備 1. 操作系統要求 Kafka 可以在多種 Linux 發行版上運行&#xff0c;本文以 CentOS 7 為例&#xff0c;其他發行版步驟類似&#xff0c;只需調整包管理命令。 2. Java 環境要…

解析工業機器視覺中的飛拍技術

在工業機器視覺的領域&#xff0c;"飛拍"這個術語時常被提起&#xff0c;尤其是在高速檢測和動態捕捉的場景中。但你真的了解飛拍是什么嗎&#xff1f;它到底如何工作&#xff0c;能為工業應用帶來哪些突破性改進呢&#xff1f;讓我們一起來解密。1. 飛拍的核心概念 …

[特殊字符]企業游學 | 探秘字節,解鎖AI科技新密碼

寶子們&#xff0c;想知道全球科技巨頭字節跳動的成功秘籍嗎&#xff1f;一場企業游學&#xff0c;帶你深入字節跳動創新基地&#xff0c;探索AI新科技&#xff0c;揭開規模化增長背后的神秘面紗?字節跳動&#xff1a;全球經濟價值的創造者字節跳動可太牛啦&#xff01;TikTok…

主流大數據框架深度解析:從介紹到選型實戰

主流大數據框架深度解析:從介紹到選型實戰 在數據驅動的時代,選擇合適的大數據處理框架是構建高效、可靠數據平臺的關鍵。 深入剖析 Hadoop MapReduce、Apache Spark、Apache Flink 和 Kafka Streams 四大主流框架,從框架介紹、具體使用場景、優缺點、選擇建議到實際案例,…

座艙HMI軟件開發架構:核心功能與案例解析

隨著智能座艙的持續演進&#xff0c;HMI&#xff08;Human Machine Interface&#xff0c;人與機器交互界面&#xff09;系統已從單一的顯示控制器演變為集多屏聯動、多模態交互、車載服務集成于一體的智能系統&#xff0c;需要一個多系統、多設備協同運行的復雜架構來支撐。本…

把“思考”塞進 1 KB:我用純 C 語言給單片機手搓了一個微型 Transformer 推理引擎

標簽&#xff1a;TinyML、Transformer、單片機、Cortex-M、量化、KV-Cache、裸機編程 ---- 1. 為什么要在 64 KB SRAM 的 MCU 上跑 Transformer&#xff1f; 2024 年以前&#xff0c;TinyML ≈ CNN CMSIS-NN&#xff0c;做語音喚醒或簡單分類就到頭了。 但產品同事突然拍腦袋&…

什么是CLI?

什么是CLI&#xff1f;CLI&#xff08;Command Line Interface&#xff09;是命令行界面的縮寫&#xff0c;是一種通過文本命令與計算機程序交互的方式。通俗比喻CLI就像是一個"智能助手"&#xff1a;你輸入命令&#xff0c;它執行任務就像和機器人對話一樣&#xff…

mysql基本sql語句大全

十分想念順店雜可。。。以下是 MySQL 中常用的基本 SQL 語句大全&#xff0c;按功能分類整理&#xff0c;包含語法和示例&#xff0c;方便參考使用&#xff1a;一、數據庫操作&#xff08;DDL&#xff09;用于創建、刪除、切換數據庫。創建數據庫-- 基本語法 CREATE DATABASE […

構建響應式在線客服聊天系統的前端實踐 Vue3+ElementUI + CSS3

構建響應式客服聊天系統的前端實踐在當今數字化時代&#xff0c;客服系統已成為企業與客戶溝通的重要橋梁。一個優秀的在線客服系統不僅需要功能完善&#xff0c;還需要在各種設備上都能提供良好的用戶體驗。本文將介紹如何構建一個響應式的客服聊天界面&#xff0c;確保在桌面…

C語言memcpy函數詳解:高效內存復制的實用工具

目錄1. memcpy函數是什么&#xff1f;函數原型2. memcpy函數的用法運行結果&#xff1a;代碼解析3. memcpy函數的注意事項3.1 內存區域不重疊3.2 緩沖區大小管理3.3 指針有效性3.4 性能優勢3.5 平臺兼容性4. 實際應用場景4.1 數組復制4.2 動態內存復制4.3 結構體復制4.4 緩沖區…

多級緩存架構:新品咖啡上線引發的數據庫壓力風暴與高并發實戰化解方案

一、背景&#xff1a;新品咖啡風暴與數據庫之痛想象一下&#xff1a;某知名咖啡品牌推出限量版“星空冷萃”&#xff0c;通過社交媒體引爆流量。上午10點開售瞬間&#xff0c;APP與網站涌入數十萬用戶&#xff0c;商品詳情頁、庫存查詢請求如海嘯般涌向后臺。傳統架構下&#x…

888. 公平的糖果交換

目錄 題目鏈接&#xff1a; 題目&#xff1a; 解題思路&#xff1a; 代碼&#xff1a; 總結&#xff1a; 題目鏈接&#xff1a; 888. 公平的糖果交換 - 力扣&#xff08;LeetCode&#xff09; 題目&#xff1a; 解題思路&#xff1a; 前一個數組和sumA,后一個數組sumB,然…

Day01 項目概述,環境搭建

軟件開發整體介紹 軟件開發流程 需求分析&#xff1a;需求規格說明書、產品原型 設計&#xff1a;UI 設計、數據庫設計&#xff0c;接口設計 編碼&#xff1a;項目代碼、單元測試 測試&#xff1a;測試用例、測試報告 上線運維&#xff1a;軟件環境安裝、配置 角色分工 項…

Perl Socket 編程

Perl Socket 編程 引言 Perl 語言作為一種強大的腳本語言,在系統管理和網絡編程領域有著廣泛的應用。Socket 編程是網絡編程的核心,它允許程序在網絡中進行數據傳輸。本文將詳細介紹 Perl 語言中的 Socket 編程,包括 Socket 的概念、創建、通信以及一些高級應用。 Socket…