news 2026/5/11 21:07:44

鸿蒙网络请求从入门到精通:HttpURLConnection+第三方库,GET/POST/文件上传全覆盖

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙网络请求从入门到精通:HttpURLConnection+第三方库,GET/POST/文件上传全覆盖

📖鸿蒙NEXT开发实战系列| 第22篇 | 网络篇 🎯适合人群:有鸿蒙基础的开发者 ⏰阅读时间:约15分钟 | 💻开发环境:DevEco Studio 5.0+

导航:上一篇:数据存储篇 | 系列目录 | 下一篇:WebSocket篇


网络请求是现代App的必备能力!无论是获取用户信息、提交表单数据,还是上传文件图片,都离不开网络请求。本文从鸿蒙原生 HttpURLConnection 讲起,再到 axios 等第三方库的使用,覆盖 GET 请求、POST 提交、文件上传、请求拦截、错误处理等全场景,附完整封装代码,助你一文掌握鸿蒙网络编程。


目录

  • 一、权限配置:网络请求的第一步

  • 二、HttpURLConnection 基础用法

  • 三、GET 请求实战

  • 四、POST 请求实战

  • 五、PUT 与 DELETE 请求

  • 六、文件上传实现

  • 七、使用 axios 第三方库

  • 八、网络请求工具类封装

  • 九、请求拦截器与错误处理

  • 十、最佳实践与性能优化

  • 总结


一、权限配置:网络请求的第一步

在鸿蒙系统中,进行网络请求必须先声明网络权限。否则请求会直接失败。

1.1 声明网络权限

module.json5文件中添加INTERNET权限:

{ "module": { "name": "entry", "type": "entry", "requestPermissions": [ { "name": "ohos.permission.INTERNET", "reason": "用于访问网络获取数据", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } } ] } }

注意:鸿蒙 NEXT 版本中,INTERNET权限属于system_grant类型,无需用户手动授权,声明即可使用。

1.2 网络状态检测

建议在请求前检测网络状态:

import { connection } from '@kit.NetworkKit'; // 检测网络是否可用 async function checkNetwork(): Promise<boolean> { try { const netHandle = await connection.getDefaultNet(); const netCapabilities = await connection.getNetCapabilities(netHandle); return netCapabilities?.bearerTypes?.length > 0; } catch (err) { console.error('网络检测失败', err); return false; } }

二、HttpURLConnection 基础用法

http模块是鸿蒙提供的原生网络请求 API,无需引入第三方库即可使用。

2.1 基础引入

import { http } from '@kit.NetworkKit';

2.2 创建请求对象

// 创建 httpRequest 实例 const httpRequest = http.createHttp(); // 请求配置 const requestOptions: http.HttpRequestOptions = { method: http.RequestMethod.GET, header: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, extraData: '', // POST 请求体 connectTimeout: 10000, // 连接超时 10 秒 readTimeout: 10000 // 读取超时 10 秒 };

三、GET 请求实战

GET 请求是最常见的请求方式,用于获取服务器数据。

3.1 基础 GET 请求

import { http } from '@kit.NetworkKit'; function doGetRequest() { const httpRequest = http.createHttp(); httpRequest.request( 'https://api.example.com/users', { method: http.RequestMethod.GET, header: { 'Content-Type': 'application/json' }, connectTimeout: 10000, readTimeout: 10000 }, (err, data) => { if (!err) { // 请求成功 console.info('状态码:', data.responseCode); const result = JSON.parse(data.result as string); console.info('返回数据:', JSON.stringify(result)); } else { // 请求失败 console.error('请求失败:', err.message); } // 销毁请求对象,释放资源 httpRequest.destroy(); } ); }

3.2 Promise 方式的 GET 请求

async function doGetWithPromise(): Promise<any> { const httpRequest = http.createHttp(); try { const response = await httpRequest.request( 'https://api.example.com/users', { method: http.RequestMethod.GET, header: { 'Content-Type': 'application/json' } } ); if (response.responseCode === 200) { const result = JSON.parse(response.result as string); console.info('请求成功:', result); return result; } else { throw new Error(`请求失败,状态码: ${response.responseCode}`); } } catch (err) { console.error('请求异常:', err); throw err; } finally { httpRequest.destroy(); } }

3.3 GET 请求带查询参数

function buildQueryString(params: Record<string, string>): string { return Object.entries(params) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) .join('&'); } async function doGetWithParams(params: Record<string, string>) { const httpRequest = http.createHttp(); const queryString = buildQueryString(params); const url = `https://api.example.com/users?${queryString}`; try { const response = await httpRequest.request(url, { method: http.RequestMethod.GET }); return JSON.parse(response.result as string); } finally { httpRequest.destroy(); } } // 使用示例 doGetWithParams({ page: '1', pageSize: '10', keyword: '鸿蒙' });

四、POST 请求实战

POST 请求用于向服务器提交数据,常见于登录、注册、表单提交等场景。

4.1 JSON 格式 POST 请求

async function doPostJson(url: string, data: object): Promise<any> { const httpRequest = http.createHttp(); try { const response = await httpRequest.request(url, { method: http.RequestMethod.POST, header: { 'Content-Type': 'application/json' }, extraData: JSON.stringify(data), connectTimeout: 10000, readTimeout: 10000 }); if (response.responseCode === 200 || response.responseCode === 201) { return JSON.parse(response.result as string); } else { throw new Error(`请求失败,状态码: ${response.responseCode}`); } } finally { httpRequest.destroy(); } } // 使用示例:用户登录 async function login(username: string, password: string) { const result = await doPostJson('https://api.example.com/login', { username, password }); console.info('登录结果:', result); }

4.2 表单格式 POST 请求

async function doFormPost(url: string, formData: Record<string, string>) { const httpRequest = http.createHttp(); const formBody = buildQueryString(formData); try { const response = await httpRequest.request(url, { method: http.RequestMethod.POST, header: { 'Content-Type': 'application/x-www-form-urlencoded' }, extraData: formBody }); return JSON.parse(response.result as string); } finally { httpRequest.destroy(); } }

五、PUT 与 DELETE 请求

RESTful API 中常见的 PUT(更新)和 DELETE(删除)请求。

5.1 PUT 请求

async function doPut(url: string, data: object): Promise<any> { const httpRequest = http.createHttp(); try { const response = await httpRequest.request(url, { method: http.RequestMethod.PUT, header: { 'Content-Type': 'application/json' }, extraData: JSON.stringify(data) }); return JSON.parse(response.result as string); } finally { httpRequest.destroy(); } } // 使用示例:更新用户信息 doPut('https://api.example.com/users/1001', { name: '张三', age: 25 });

5.2 DELETE 请求

async function doDelete(url: string): Promise<any> { const httpRequest = http.createHttp(); try { const response = await httpRequest.request(url, { method: http.RequestMethod.DELETE, header: { 'Content-Type': 'application/json' } }); return response.responseCode === 200 ? JSON.parse(response.result as string) : null; } finally { httpRequest.destroy(); } } // 使用示例:删除用户 doDelete('https://api.example.com/users/1001');

六、文件上传实现

文件上传是实际开发中的高频需求,使用 multipart/form-data 格式实现。

6.1 基础文件上传

import { http } from '@kit.NetworkKit'; import { fileIo } from '@kit.CoreFileKit'; async function uploadFile(url: string, filePath: string, fileName: string): Promise<any> { const httpRequest = http.createHttp(); try { // 读取文件为 ArrayBuffer const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY); const stat = fileIo.statSync(filePath); const arrayBuffer = new ArrayBuffer(stat.size); fileIo.readSync(file.fd, arrayBuffer); fileIo.closeSync(file); // 构建 multipart 请求 const boundary = '----HarmonyOSBoundary' + Date.now(); // 构建请求体 const headerPart = `--${boundary}\r\n` + `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n` + `Content-Type: application/octet-stream\r\n\r\n`; const footerPart = `\r\n--${boundary}--\r\n`; // 拼接完整请求体 const encoder = new util.TextEncoder(); const headerBuffer = encoder.encodeInto(headerPart); const footerBuffer = encoder.encodeInto(footerPart); const totalLength = headerBuffer.byteLength + arrayBuffer.byteLength + footerBuffer.byteLength; const bodyBuffer = new Uint8Array(totalLength); bodyBuffer.set(new Uint8Array(headerBuffer), 0); bodyBuffer.set(new Uint8Array(arrayBuffer), headerBuffer.byteLength); bodyBuffer.set(new Uint8Array(footerBuffer), headerBuffer.byteLength + arrayBuffer.byteLength); const response = await httpRequest.request(url, { method: http.RequestMethod.POST, header: { 'Content-Type': `multipart/form-data; boundary=${boundary}` }, extraData: bodyBuffer.buffer as ArrayBuffer }); return JSON.parse(response.result as string); } finally { httpRequest.destroy(); } } // 使用示例 uploadFile( 'https://api.example.com/upload', '/data/storage/el2/base/haps/entry/files/photo.jpg', 'photo.jpg' );

提示:鸿蒙 NEXT 中更推荐使用request模块的上传能力,系统会自动处理 multipart 格式。

6.2 使用系统 upload API

import { request } from '@kit.NetworkKit'; async function uploadWithSystemAPI(url: string, filePath: string) { const uploadTask = await request.uploadFile(getContext(), { url: url, method: 'POST', files: [{ filename: 'file', name: 'file', uri: filePath }], data: [{ name: 'description', value: '用户上传图片' }] }); uploadTask.on('complete', (taskState) => { console.info('上传完成:', taskState); }); uploadTask.on('fail', (taskState) => { console.error('上传失败:', taskState); }); }

七、使用 axios 第三方库

axios 是目前最流行的 HTTP 客户端库之一,鸿蒙社区也提供了适配版本。

7.1 安装 axios

ohpm install @ohos/axios

7.2 基础用法

import axios from '@ohos/axios'; // GET 请求 async function getUsers() { const response = await axios.get('https://api.example.com/users'); console.info('用户列表:', response.data); return response.data; } // POST 请求 async function createUser(userData: object) { const response = await axios.post('https://api.example.com/users', userData); console.info('创建成功:', response.data); return response.data; }

7.3 axios 配置项

import axios, { AxiosRequestConfig } from '@ohos/axios'; // 创建 axios 实例 const service = axios.create({ baseURL: 'https://api.example.com', timeout: 15000, headers: { 'Content-Type': 'application/json' } }); // 请求配置 const config: AxiosRequestConfig = { method: 'post', url: '/users', data: { name: '张三', age: 25 } }; service(config).then(response => { console.info(response.data); });

八、网络请求工具类封装

实际开发中,我们需要封装一个通用的网络请求工具类,统一管理请求配置和错误处理。

8.1 完整封装代码

// utils/HttpRequest.ets import { http } from '@kit.NetworkKit'; // 响应数据结构 interface ApiResponse<T = any> { code: number; message: string; data: T; } // 请求配置 interface RequestConfig { url: string; method?: http.RequestMethod; data?: object | string; header?: Record<string, string>; timeout?: number; } class HttpRequest { private baseUrl: string = ''; private defaultHeader: Record<string, string> = { 'Content-Type': 'application/json' }; private timeout: number = 15000; // 设置基础配置 setBaseUrl(url: string): void { this.baseUrl = url; } setToken(token: string): void { this.defaultHeader['Authorization'] = `Bearer ${token}`; } // 核心请求方法 async request<T = any>(config: RequestConfig): Promise<ApiResponse<T>> { const httpRequest = http.createHttp(); const fullUrl = this.baseUrl + config.url; try { const response = await httpRequest.request(fullUrl, { method: config.method || http.RequestMethod.GET, header: { ...this.defaultHeader, ...config.header }, extraData: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, connectTimeout: config.timeout || this.timeout, readTimeout: config.timeout || this.timeout }); const result: ApiResponse<T> = JSON.parse(response.result as string); if (response.responseCode === 200) { return result; } else { throw new Error(result.message || `请求失败: ${response.responseCode}`); } } catch (err) { console.error('请求异常:', err); throw err; } finally { httpRequest.destroy(); } } // GET 请求 async get<T = any>(url: string, params?: Record<string, string>): Promise<ApiResponse<T>> { let fullUrl = url; if (params) { const queryString = Object.entries(params) .map(([key, value]) => `${key}=${encodeURIComponent(value)}`) .join('&'); fullUrl += `?${queryString}`; } return this.request<T>({ url: fullUrl, method: http.RequestMethod.GET }); } // POST 请求 async post<T = any>(url: string, data?: object): Promise<ApiResponse<T>> { return this.request<T>({ url, method: http.RequestMethod.POST, data }); } // PUT 请求 async put<T = any>(url: string, data?: object): Promise<ApiResponse<T>> { return this.request<T>({ url, method: http.RequestMethod.PUT, data }); } // DELETE 请求 async delete<T = any>(url: string): Promise<ApiResponse<T>> { return this.request<T>({ url, method: http.RequestMethod.DELETE }); } } // 导出单例 export const httpRequest = new HttpRequest();

8.2 使用示例

import { httpRequest } from '../utils/HttpRequest'; // 初始化配置 httpRequest.setBaseUrl('https://api.example.com'); httpRequest.setToken('your-token-here'); // 页面中使用 @Entry @Component struct UserListPage { @State users: User[] = []; async aboutToAppear() { try { // GET 请求获取用户列表 const result = await httpRequest.get<User[]>('/users', { page: '1', pageSize: '10' }); this.users = result.data; // POST 请求创建用户 await httpRequest.post('/users', { name: '新用户', age: 20 }); // PUT 请求更新用户 await httpRequest.put('/users/1001', { name: '更新后的名字' }); // DELETE 请求删除用户 await httpRequest.delete('/users/1001'); } catch (err) { console.error('操作失败:', err); } } build() { List({ space: 10 }) { ForEach(this.users, (user: User) => { ListItem() { Text(user.name) .fontSize(16) } }) } } }

九、请求拦截器与错误处理

9.1 封装拦截器

// utils/HttpInterceptor.ets import { http } from '@kit.NetworkKit'; type RequestInterceptor = (config: RequestConfig) => RequestConfig; type ResponseInterceptor = (response: any) => any; type ErrorInterceptor = (error: Error) => void; class HttpInterceptor { private requestInterceptors: RequestInterceptor[] = []; private responseInterceptors: ResponseInterceptor[] = []; private errorInterceptors: ErrorInterceptor[] = []; // 添加请求拦截器 addRequestInterceptor(interceptor: RequestInterceptor): void { this.requestInterceptors.push(interceptor); } // 添加响应拦截器 addResponseInterceptor(interceptor: ResponseInterceptor): void { this.responseInterceptors.push(interceptor); } // 添加错误拦截器 addErrorInterceptor(interceptor: ErrorInterceptor): void { this.errorInterceptors.push(interceptor); } // 执行请求拦截 applyRequestInterceptors(config: RequestConfig): RequestConfig { let processedConfig = { ...config }; for (const interceptor of this.requestInterceptors) { processedConfig = interceptor(processedConfig); } return processedConfig; } // 执行响应拦截 applyResponseInterceptors(response: any): any { let processedResponse = response; for (const interceptor of this.responseInterceptors) { processedResponse = interceptor(processedResponse); } return processedResponse; } // 执行错误拦截 applyErrorInterceptors(error: Error): void { for (const interceptor of this.errorInterceptors) { interceptor(error); } } } export const httpInterceptor = new HttpInterceptor();

9.2 配置拦截器

import { httpInterceptor } from '../utils/HttpInterceptor'; import { router } from '@kit.ArkUI'; // 请求拦截器:自动添加 token httpInterceptor.addRequestInterceptor((config) => { const token = AppStorage.get<string>('userToken'); if (token) { config.header = { ...config.header, 'Authorization': `Bearer ${token}` }; } console.info(`[请求] ${config.method} ${config.url}`); return config; }); // 响应拦截器:统一处理响应 httpInterceptor.addResponseInterceptor((response) => { console.info(`[响应] 状态码: ${response.responseCode}`); // 业务状态码处理 if (response.data?.code === 401) { // Token 过期,跳转登录页 router.pushUrl({ url: 'pages/LoginPage' }); throw new Error('登录已过期,请重新登录'); } return response; }); // 错误拦截器:统一错误处理 httpInterceptor.addErrorInterceptor((error) => { console.error('[错误]', error.message); // 网络错误提示 if (error.message.includes('timeout')) { promptAction.showToast({ message: '网络超时,请稍后重试' }); } else if (error.message.includes('Network')) { promptAction.showToast({ message: '网络连接失败,请检查网络' }); } });

9.3 错误码处理

function handleHttpError(statusCode: number): string { const errorMap: Record<number, string> = { 400: '请求参数错误', 401: '未授权,请登录', 403: '拒绝访问', 404: '请求资源不存在', 408: '请求超时', 500: '服务器内部错误', 502: '网关错误', 503: '服务不可用', 504: '网关超时' }; return errorMap[statusCode] || `未知错误: ${statusCode}`; }

十、最佳实践与性能优化

10.1 请求并发控制

// 限制并发请求数量 async function batchRequest(urls: string[], maxConcurrent: number = 5) { const results = []; for (let i = 0; i < urls.length; i += maxConcurrent) { const batch = urls.slice(i, i + maxConcurrent); const batchResults = await Promise.all( batch.map(url => httpRequest.get(url)) ); results.push(...batchResults); } return results; }

10.2 请求缓存策略

const cacheMap = new Map<string, { data: any; timestamp: number }>(); const CACHE_DURATION = 5 * 60 * 1000; // 5 分钟缓存 async function getWithCache<T>(url: string): Promise<T> { const cached = cacheMap.get(url); if (cached && Date.now() - cached.timestamp < CACHE_DURATION) { return cached.data; } const result = await httpRequest.get<T>(url); cacheMap.set(url, { data: result.data, timestamp: Date.now() }); return result.data; }

10.3 请求重试机制

async function requestWithRetry( requestFn: () => Promise<any>, maxRetries: number = 3, delay: number = 1000 ): Promise<any> { for (let i = 0; i < maxRetries; i++) { try { return await requestFn(); } catch (err) { if (i === maxRetries - 1) throw err; console.warn(`请求失败,${delay}ms 后重试 (${i + 1}/${maxRetries})`); await new Promise(resolve => setTimeout(resolve, delay)); } } }

总结

本文从基础到进阶,完整介绍了鸿蒙网络请求的各个方面:

内容

说明

权限配置

ohos.permission.INTERNET必须声明

HttpURLConnection

原生 API,无需额外依赖

GET/POST/PUT/DELETE

覆盖 RESTful 全部请求方式

文件上传

支持 multipart 和系统 upload API

axios 第三方库

更简洁的 API,支持拦截器

工具类封装

统一管理请求配置和错误处理

拦截器

请求/响应拦截,统一添加 token

性能优化

并发控制、缓存策略、重试机制

选择建议

  • 简单项目:直接使用http模块

  • 复杂项目:封装工具类 + 拦截器

  • 团队协作:使用 axios 等成熟库

掌握这些知识,你就能应对鸿蒙开发中 99% 的网络请求场景了!


📚系列文章推荐

  • 第21篇:数据持久化之首选项与关系型数据库

  • 第23篇:WebSocket 实时通信实战

  • 第24篇:网络状态监听与弱网优化

  • 第25篇:网络请求缓存策略详解


标签鸿蒙网络请求HTTPaxios网络编程HarmonyOSHttpURLConnection文件上传请求封装


💡下期预告:WebSocket 实时通信实战,实现聊天室功能!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/11 21:04:51

3分钟掌握NeuroSynth:Python脑成像元分析快速入门指南

3分钟掌握NeuroSynth&#xff1a;Python脑成像元分析快速入门指南 【免费下载链接】neurosynth Neurosynth core tools 项目地址: https://gitcode.com/gh_mirrors/ne/neurosynth 想要快速处理功能磁共振成像&#xff08;fMRI&#xff09;数据并进行神经影像元分析吗&am…

作者头像 李华
网站建设 2026/5/11 21:01:30

概率计算与可信AI:从架构到应用的全面解析

1. 概率计算与可信AI的架构革命 在医疗诊断和自动驾驶等高风险决策场景中&#xff0c;AI系统仅给出确定性预测是远远不够的。去年参与一个医疗影像分析项目时&#xff0c;我们团队发现&#xff1a;当模型需要判断肿瘤恶性概率时&#xff0c;传统神经网络输出的单一数值根本无法…

作者头像 李华
网站建设 2026/5/11 20:59:59

AI科技热点日报 | 2026年5月11日

文章目录 AI科技前沿观察 | 2026年5月11日一、大型模型领域动态&#xff1a;技术发展与市场关注二、AI算力投入与技术生态发展字节跳动AI算力投入英伟达在AI领域的投资布局AI企业技术发展与资金支持 三、AI政策与标准体系建设人工智能终端智能化分级国家标准发布智能体规范文件…

作者头像 李华