HarmonyOS 6.0 下载上传与网络文件
网络文件操作在HarmonyOS NEXT里不是用XMLHttpRequest或者第三方库——官方给了一套request APIdownloadFile/uploadFile直接搞定。但进度回调、任务管理、断点续传这些细节如果没踩过坑第一次写容易翻车。下载文件kit.NetworkKit的request模块提供downloadFile方法import{request}fromkit.NetworkKit;letdownloadTask:request.DownloadTaskawaitrequest.downloadFile(context,{url:https://example.com/file.zip,filePath:/data/storage/el2/base/files/file.zip,enableMetered:true,enableRoaming:true,title:下载文件,description:正在下载...});参数说明url— 下载地址必须HTTPSHTTP需要配置cleartextfilePath— 保存路径沙箱目录下不填则存临时目录enableMetered— 是否允许计费网络下载enableRoaming— 是否允许漫游下载filePath必须写沙箱路径常用几个/data/storage/el2/base/files/— 应用私有文件目录/data/storage/el2/base/cache/— 缓存目录/data/storage/el2/base/temp/— 临时目录进度监听下载进度通过on(‘progress’)监听StatedownloadPercent:number0;downloadTask.on(progress,(receivedSize:number,totalSize:number){if(totalSize0){this.downloadPercentMath.floor(receivedSize/totalSize*100);}});downloadTask.on(complete,(){this.downloadPercent100;this.addLog(下载完成);});downloadTask.on(fail,(err:number){this.addLog(下载失败: err.toString());});receivedSize和totalSize单位是字节。有些服务器不返回Content-LengthtotalSize会是-1这种情况百分比没法算得用已下载字节数代替。任务控制下载任务可以暂停、恢复、移除downloadTask.pause();// 暂停downloadTask.resume();// 恢复(断点续传)downloadTask.remove();// 删除任务// 查询任务信息letinfo:request.DownloadInfoawaitdownloadTask.query();// info.downloadedSize, info.downloadTotalSize, info.status等断点续传的关键pause之后resume会从断点继续不需要手动记录位置。但前提是服务器支持Range请求否则resume会从头下载。任务状态枚举request.DownloadStatus.SUCCESS// 0request.DownloadStatus.RUNNING// 1request.DownloadStatus.PAUSED// 2request.DownloadStatus.FAILED// 3上传文件uploadFile用于文件上传支持multipart/form-dataletuploadTask:request.UploadTaskawaitrequest.uploadFile(context,{url:https://example.com/upload,method:POST,header:{Authorization:Bearer token123},files:[{filename:photo.jpg,name:file,uri:internal://cache/photo.jpg,type:jpg}],data:[{name:userId,value:12345}]});files数组指定要上传的文件filename— 服务端收到的文件名name— 表单字段名uri— 本地文件路径用internal://协议type— 文件MIME类型简写data数组是额外的表单字段键值对形式。上传进度监听跟下载类似uploadTask.on(progress,(uploadedSize:number,totalSize:number){this.uploadPercentMath.floor(uploadedSize/totalSize*100);});uploadTask.on(complete,(taskStates:Arrayrequest.TaskState){this.addLog(上传完成);});uploadTask.on(fail,(taskStates:Arrayrequest.TaskState){this.addLog(上传失败);});注意complete和fail的回调参数是TaskState数组不是简单的errcode。每个TaskState包含responseCode等详细信息。HTTP方法与HeaderdownloadFile默认GETuploadFile可以指定method。常见配置{url:https://api.example.com/data,method:PUT,header:{Content-Type:application/json,Authorization:Bearer token,X-Custom-Header:value}}需要token验证的接口在header里带就行。注意Content-Type在uploadFile中不要手动设置multipart/form-data系统会自动处理boundary。多文件并行下载实际场景经常需要同时下载多个文件。每个downloadFile调用返回独立的DownloadTask可以分别管理interfaceDownloadItem{url:string;name:string;task:request.DownloadTask|null;progress:number;status:string;}StatedownloadList:DownloadItem[][];asyncstartDownload(item:DownloadItem,index:number):Promisevoid{consttask:request.DownloadTaskawaitrequest.downloadFile(this.context,{url:item.url,filePath:/data/storage/el2/base/files/item.name});constnewList:DownloadItem[]this.downloadList.slice();newList[index]{...item,task:task,status:downloading};this.downloadListnewList;task.on(progress,(received:number,total:number){constpercent:numbertotal0?Math.floor(received/total*100):0;constupdated:DownloadItem[]this.downloadList.slice();updated[index]{...updated[index],progress:percent};this.downloadListupdated;});task.on(complete,(){constupdated:DownloadItem[]this.downloadList.slice();updated[index]{...updated[index],status:done,progress:100};this.downloadListupdated;});}每个任务独立监听进度互不干扰。State数组要用slice替换来触发刷新。网络状态感知下载前检查网络状态是好习惯import{connection}fromkit.NetworkKit;letnetConnection:connection.NetConnectionconnection.createNetConnection();netConnection.on(netAvailable,(){this.addLog(网络可用);});netConnection.on(netLost,(){this.addLog(网络断开);// 暂停所有下载});netConnection.register((){});网络断开时主动暂停下载网络恢复时resume避免浪费流量重试。下载文件校验下载完成别忘了校验完整性import{hash}fromkit.BasicServicesKit;downloadTask.on(complete,async(){constfilePath:string/data/storage/el2/base/files/file.zip;constmd5:stringawaithash.hash(filePath,md5);if(md5expectedMd5){this.addLog(校验通过);}else{this.addLog(文件损坏);}});hash模块支持md5/sha1/sha256大文件计算是异步的。权限与配置下载上传需要网络权限module.json5声明{ requestPermissions: [ { name: ohos.permission.INTERNET } ] }如果要访问HTTP非HTTPS需要配置network security config{ domainSettings: { domains: [ { name: example.com, cleartext: true } ] } }踩坑清单filePath如果目录不存在会直接失败先确认目录存在downloadTask.on(‘progress’)在有些设备上回调频率很低约1秒1次不要拿来做精确的实时进度条remove()之后不能再resume上传uri必须用internal://协议不能直接写/data/storage路径并发下载数量没有硬限制但太多会占满带宽建议控制在3-5个上传的complete回调参数是数组要取[0]看具体状态断点续传依赖服务器Range支持测试时确认服务器配置大文件下载建议先用HEAD请求获取Content-Length网络文件操作的核心是任务化思维——每个下载/上传是一个独立任务有生命周期有状态流转有进度回调。理解了这个模型暂停/恢复/取消这些操作就是顺理成章的事。