
文章目录前言前言两种 Picker 定位对比PhotoViewPicker 选图DocumentViewPicker 选文件文件读取与保存沙箱路径说明写在最后前言选图片、选文件App 里最基础的操作之一。但 HarmonyOS 的文件选择跟 Android 不太一样它用了一套 Picker 体系不是直接给你文件路径而是给你一个 URI——这就涉及到沙箱路径、临时权限、文件拷贝等一系列问题。我第一次用的时候文件选到了却读不出来折腾了好一阵才搞明白。今天把 PhotoViewPicker 和 DocumentViewPicker 的用法彻底讲清楚。前言HarmonyOS7 的文件选择器分两种PhotoViewPicker选图片/视频DocumentViewPicker选文档类文件。两种 Picker 用法类似但返回的 URI 权限不同处理方式也有差异。这篇文章会从选图、选文件、读文件、存文件、沙箱路径一条龙讲完。两种 Picker 定位对比先搞清楚什么时候用哪个对比维度PhotoViewPickerDocumentViewPicker用途选择图片和视频选择任意文档文件导入模块kit.CoreFileKitkit.CoreFileKit核心方法select()select()保存方法save()save()返回类型图片/视频 URI文档 URI文件过滤支持 MIME 类型过滤支持后缀名过滤多选支持maxSelectNumber支持maxSelectNumber临时权限只读只读简单判断选头像、选相册照片 → PhotoViewPicker选 PDF、选 Excel → DocumentViewPicker。PhotoViewPicker 选图选图片是最常见的场景代码如下import{picker}fromkit.CoreFileKit;import{BusinessError}fromkit.BasicServicesKit;StateselectedUri:string;asyncpickPhoto():Promisevoid{try{letphotoSelectOptionsnewpicker.PhotoSelectOptions();photoSelectOptions.MIMETypepicker.PhotoViewMIMETypes.IMAGE_TYPE;photoSelectOptions.maxSelectNumber1;letphotoViewPickernewpicker.PhotoViewPicker();letphotoSelectResultawaitphotoViewPicker.select(photoSelectOptions);if(photoSelectResult.photoUris.length0){this.selectedUriphotoSelectResult.photoUris[0];console.info(选中的图片URI:${this.selectedUri});}}catch(e){leterreasBusinessError;console.error(选图失败: code${err.code}, msg${err.message});}}逐行讲解MIMEType: IMAGE_TYPE— 只显示图片类型。如果也想选视频改成IMAGE_VIDEO_TYPEmaxSelectNumber: 1— 最多选 1 张。改成 9 就是多选select()是异步方法返回PhotoSelectResultphotoSelectResult.photoUris是选中的 URI 数组多选时会有多个URI 不是文件路径不能直接拿来显示图片需要用ohos.file.picker返回的 URI 配合 Image 组件使用Image 组件可直接加载 URIImage 组件可以直接用 URI 显示图片Image(this.selectedUri).width(200).height(200).objectFit(ImageFit.Cover)DocumentViewPicker 选文件选 PDF、Word 这类文档就得用 DocumentViewPickerasyncpickDocument():Promisevoid{try{letdocumentSelectOptionsnewpicker.DocumentSelectOptions();documentSelectOptions.maxSelectNumber1;documentSelectOptions.fileSuffixFilters[.pdf,.doc,.docx,.xls];letdocumentViewPickernewpicker.DocumentViewPicker(this.getUIContext().getHostContext()ascommon.UIAbilityContext);letdocumentSelectResultawaitdocumentViewPicker.select(documentSelectOptions);if(documentSelectResult.length0){this.selectedDocUridocumentSelectResult[0];console.info(选中的文件URI:${this.selectedDocUri});}}catch(e){leterreasBusinessError;console.error(选文件失败: code${err.code}, msg${err.message});}}关键讲解fileSuffixFilters— 按文件后缀过滤只显示指定类型的文件。不设置则显示所有文件DocumentViewPicker构造时需要传入 ContextPhotoViewPicker 不需要这是个区别记一下返回的documentSelectResult直接就是 URI 数组不像 PhotoSelectResult 那样包了一层文件读取与保存拿到 URI 后怎么读文件内容这就要用到kit.CoreFileKit里的fileIoimport{fileIoasfs,fileUri}fromkit.CoreFileKit;asyncreadFileFromUri(uri:string):Promisestring{letfilefs.openSync(uri,fs.OpenMode.READ_ONLY);letstatfs.statSync(file.fd);letbuffernewArrayBuffer(stat.size);fs.readSync(file.fd,buffer);fs.closeSync(file);// 假设是文本文件lettextDecoderutil.TextDecoder.create(utf-8);returntextDecoder.decodeToString(newUint8Array(buffer));}逐行讲解fs.openSync(uri, READ_ONLY)— 通过 URI 打开文件返回文件描述符fs.statSync(file.fd)— 获取文件大小fs.readSync— 读取文件内容到 ArrayBuffer读完后必须 closeSync不然文件描述符泄漏保存文件到公共目录如果你要把文件保存到文件管理器可见的公共目录用 Picker 的save()方法asyncsaveFileToPublic():Promisevoid{letdocumentSaveOptionsnewpicker.DocumentSaveOptions();documentSaveOptions.newFileNames[report.pdf];letdocumentViewPickernewpicker.DocumentViewPicker(this.getUIContext().getHostContext()ascommon.UIAbilityContext);letsaveResultawaitdocumentViewPicker.save(documentSaveOptions);console.info(保存路径:${saveResult[0]});}save()会弹出系统文件选择器让用户选保存位置。返回的是保存后的 URI。沙箱路径说明这是很多人搞不清楚的地方。HarmonyOS 的文件系统是沙箱隔离的路径说明其他应用可见context.filesDir应用私有文件目录否context.cacheDir缓存目录系统可能清理否context.tempDir临时文件目录否Picker 返回的 URI临时授权的公共文件 URI只读临时权限save() 返回的 URI用户选定的公共目录是核心问题Picker 返回的 URI 只有临时只读权限这个权限不能转授给其他组件比如文件预览。如果你要预览文件得先把文件拷贝到沙箱asynccopyToSandbox(pickerUri:string):Promisestring{letfilefs.openSync(pickerUri,fs.OpenMode.READ_ONLY);letpathDirgetContext().filesDir;letsandboxPathpathDir/file.name;fs.copyFileSync(file.fd,sandboxPath);fs.closeSync(file);returnfileUri.getUriFromPath(sandboxPath);}逐行讲解file.name— 从 URI 中提取文件名copyFileSync— 把文件从公共目录拷到沙箱fileUri.getUriFromPath— 把沙箱路径转成 URI给预览组件用敲黑板Picker 拿到的 URI 是临时的App 重启后就失效了。需要持久使用必须拷贝到沙箱。写在最后文件选择这块最大的坑就是 URI 权限问题。Picker 给你的 URI 只有临时只读权限想预览、想持久化都得先拷贝到沙箱。我之前就在这卡了好久文件选到了但 Preview Kit 死活打不开最后才发现是权限没转授的问题。记住一句话Picker 选完先拷贝沙箱里才是你的地盘。