05-Flutter 鸿蒙实战 05:照片上传功能,image_picker + Multipart 进度上传 05. Flutter 鸿蒙实战 05照片上传功能image_picker Multipart 进度上传从图库选择照片校验类型和大小再把字节流上传到后端。上传页职责上传页位于lib/features/upload/upload_page.dart。它不是一个简单的按钮页面而是包含选择照片、预览、MIME 校验、大小限制、上传进度、处理状态、照片管理列表等多个状态。页面状态字段比较多但每个都对应真实交互XFile?_file;Uint8List?_bytes;String?_mimeType;String?_error;String?_success;bool _pickingfalse;bool _uploadingfalse;bool _processingfalse;double _progress0;ListAlbumPhoto_photosconst[];_picking表示正在调起图库_uploading表示字节正在上传_processing表示后端正在识别照片并生成故事。三个状态分开页面才能给出准确提示。选择照片项目使用image_picker并且依赖来自 OpenHarmony 适配仓库。选择图片的代码如下finalfileawait_picker.pickImage(source:ImageSource.gallery,imageQuality:92,);if(filenull)return;finalbytesawaitfile.readAsBytes();finalmimeTypelookupMimeType(file.name,headerBytes:bytes.take(16).toList());这里没有只看文件后缀而是用文件名和头部字节一起判断 MIME。移动端上传图片时用户文件来源不可控后缀并不总是可靠。类型和大小校验项目限制最大 20MB并允许常见图片格式if(bytes.length_maxBytes){throwconstFormatException(照片不能超过 20 MB);}if(!const{image/jpeg,image/png,image/webp,image/heic}.contains(mimeType)){throwconstFormatException(仅支持 JPEG、PNG、WebP 和 HEIC 图片);}这一步放在前端做可以减少无效上传。后端仍然应该做最终校验但前端提前提示会让体验更顺。上传照片上传时调用ApiClient.uploadPhotofinalresponseawaitapiClient.uploadPhoto(bytes:bytes,filename:file.name,mimeType:mimeType,onProgress:(value){if(mounted)setState(()_progressvalue);},);页面上对应显示线性进度条if(_uploading)...[constSizedBox(height:16),LinearProgressIndicator(value:_progress),constSizedBox(height:8),Text(正在上传${(_progress*100).round()}%,textAlign:TextAlign.center,),]这种进度来自真实字节写入不是假 loading。大图上传时用户能看到进度变化。上传列表页面进入后会加载当前用户上传过的照片Futurevoid_loadPhotos()async{finalapiAuthScope.of(context).apiClient;setState((){_photosLoadingtrue;_photosErrornull;});try{finalrowsawaitapi.getJsonList(/api/photos);finalphotosrows.whereTypeMapString,dynamic().map(AlbumPhoto.fromJson).toList();setState((){_photosphotos;_photosLoadingfalse;});}catch(exception){setState((){_photosLoadingfalse;_photosError_message(exception);});}}上传页不只负责“新增”还承担照片管理入口查看原图、打开对话、编辑元数据、开始活化、从上传列表移除、删除照片。OpenHarmony 适配注意点image_picker必须使用带 ohos 实现的版本。依赖写法如下image_picker:git:url:https://gitcode.com/openharmony-tpc/flutter_packages.gitpath:packages/image_picker/image_picker如果换成普通依赖Android 可能正常鸿蒙构建就可能缺少平台实现。Flutter 鸿蒙项目选择插件时第一眼要看有没有ohos适配。扩展拆解上传页的状态拆分上传页不能只用一个loading。这个项目拆成了_picking、_uploading、_processing、_photosLoading、_clearingUploads等多个状态。它们分别对应选择图片、上传文件、后端处理、加载照片列表、清空上传列表。boolget_busy_picking||_uploading||_processing;用户选择图片时上传按钮要禁用文件正在上传时清除按钮也要禁用后端正在处理时不能重复提交同一张照片。把状态拆清楚后页面行为才不会混乱。防重复操作照片列表里的删除、移除、活化使用了不同的 Set 保存忙碌状态finalSetString_removing{};finalSetString_deleting{};finalSetString_animating{};这种写法比全局禁用整个页面更细。某张照片正在删除时只禁用这张照片对应的按钮其他照片仍然可以操作。al Set _removing {};final Set _deleting {};final Set _animating {};这种写法比全局禁用整个页面更细。某张照片正在删除时只禁用这张照片对应的按钮其他照片仍然可以操作。