050 — Core File Kit 与文件选择器:沙箱文件管理与批量授权
简介
鸿蒙系统采用沙箱文件机制来保障用户数据安全——每个应用只能访问自己的沙箱目录,访问外部文件需要通过文件选择器(Picker)获取用户授权。MoneyTrack 在反馈模块中完整实践了这一流程:用户通过 Picker 选择图片或文件,系统返回 URI 后,应用通过fileUri.getUriFromPath()完成路径转换,再读取文件内容进行上传。批量授权机制让用户可以一次选择多个文件并统一授权,避免了逐个确认的繁琐操作。
核心知识点
1. 沙箱文件目录结构
鸿蒙应用的沙箱路径遵循以下目录结构:
/data/storage/el2/base/haps/entry/files/ ← 应用文件目录 /data/storage/el2/base/haps/entry/cache/ ← 缓存目录(系统可清理) /data/storage/el2/base/data/ ← 应用数据库和 SharedPreferences /data/storage/el2/base/preferences/ ← 首选项存储目录沙箱分为两个层级:
- 应用沙箱:应用私有目录,无需授权即可读写,但数据随应用卸载而删除。
- 用户沙箱:用户公开目录(如相册、下载),需要通过 Picker 授权访问。
2. fileUri URI 转换
fileUri模块提供沙箱路径与 URI 的相互转换:
fileUri.getUriFromPath(path):将本地沙箱路径转换为file://协议 URI。fileUri.getPathFromUri(uri):将 URI 转换回本地路径。- URI 格式的跨进程传递更为安全和标准。
3. 文件选择器(Picker)
Picker 是系统提供的标准文件选择界面,核心 Picker 类型如下:
| Picker 类型 | 适用场景 | 核心参数 |
|---|---|---|
| PhotoViewPicker | 图片/视频选择 | maxCount, selectType |
| DocumentViewPicker | 文档选择(PDF/Word/Excel) | maxCount, fileSuffixFilters |
| AudioViewPicker | 音频文件选择 | maxCount |
PhotoViewPicker 完整参数说明:
| 参数 | 类型 | 说明 | 示例 |
|---|---|---|---|
| maxCount | number | 最大选择数量(默认 10) | 9 |
| selectType | PhotoSelectType | 筛选类型:IMAGE、VIDEO、IMAGE_VIDEO | IMAGE |
DocumentViewPicker用于选择文档文件,支持按文件后缀筛选:
constdocPicker=newDocumentViewPicker();constresult=awaitdocPicker.select({maxCount:5,fileSuffixFilters:['.pdf','.doc','.docx']});// result 返回选中文件的 URI 列表4. PersistableURI 持久化授权
Picker 返回的 URI 默认是临时授权——应用在前台运行时有效。如果需要后台或下次启动时继续访问,需要通过PersistableURI机制持久化授权。持久化后,应用在后续启动时无需用户再次授权即可访问这些文件。
5. 文件选择→授权→URI转换→读取→上传完整流程
项目代码案例
反馈模块中的上传文件处理:
文件路径:feature_feedback组件
import{photoAccessHelper}from'@kit.MediaLibraryKit';import{fileUri}from'@kit.CoreFileKit';import{fileIoasfs}from'@kit.CoreFileKit';asyncfunctionpickAndUpload(){// 打开 Picker 选择图片constpicker=newphotoAccessHelper.PhotoViewPicker();constresult=awaitpicker.select({maxCount:9,// 最多选择 9 张selectType:photoAccessHelper.PhotoSelectType.IMAGE// 仅图片});for(consturiofresult.photoUris){// URI 转路径constpath=fileUri.getPathFromUri(uri);// 读取文件并上传awaituploadFile(uri,path);}}asyncfunctionuploadFile(uri:string,path:string){// 使用 fs 打开文件读取内容constfile=fs.openSync(path,fs.OpenMode.READ_ONLY);constbuffer=newArrayBuffer(4096);fs.readSync(file.fd,buffer);fs.closeSync(file);// 通过 FormData 上传constformData=newFormData();formData.append('file',uri);returnaxios.post('/api/feedback/upload',formData,{headers:{'Content-Type':'multipart/form-data'}});}// 持久化授权的示例asyncfunctionpersistFileAccess(uris:string[]){constpersistentUri=newPersistableURI(uris[0]);awaitpersistentUri.persist();// 持久化授权console.info('文件访问权限已持久化');}使用 DocumentViewPicker 选择文档:
import{DocumentViewPicker}from'@kit.CoreFileKit';asyncfunctionpickDocument(){constdocPicker=newDocumentViewPicker();constresult=awaitdocPicker.select({maxCount:3,fileSuffixFilters:['.pdf','.xlsx','.docx']});if(result&&result.length>0){for(constdocUriofresult){constpath=fileUri.getPathFromUri(docUri);// 处理文件...}}}最佳实践
- 合理设置 maxCount:根据业务需求设置最大选择数量,图片上传建议 9 张以内,文档选择建议 5 张以内,避免一次性选择过多文件导致内存溢出。
- 使用 selectType 过滤:明确指定
selectType,让用户在 Picker 中只看到需要的文件类型,提升选择效率。 - 及时释放文件资源:使用
fs.openSync后务必在 finally 中调用fs.closeSync,避免文件句柄泄漏。 - 临时授权 vs 持久化授权:大多数上传场景使用临时授权即可;只有需要跨应用启动周期访问的场景(如下载目录中的文件)才需要 PersistableURI。
- URI 优先于路径传递:URI 是跨进程传递的标准格式,优先使用 URI 而非拼接后的路径,确保兼容性和安全性。
- 错误处理:Picker 可能被用户取消(返回 null)或文件被删除(读取失败),务必做好错误处理并给出用户友好的提示。
推荐参考文档
- Core File Kit 文件管理指南
- PhotoViewPicker / DocumentViewPicker API 参考
- PersistableURI API 参考