系列文章《鸿蒙开发从入门到专家》第 24 篇 · 中级
数据持久化不止数据库一条路。日志导出、图片保存、配置文件备份、用户文档编辑,这些场景都离不开文件系统。鸿蒙对文件访问做了严格隔离,理解沙盒目录和各类选择器,是写出合规应用的前提。
一、应用沙盒目录
鸿蒙每个应用都有独立的沙盒空间,应用只能直接访问自己的目录。常见路径包括:
context.filesDir:应用私有文件目录,适合持久化存储用户数据。context.cacheDir:缓存目录,系统可能在空间不足时清理。context.tempDir:临时文件目录,适合一次性使用。context.databaseDir:数据库存放目录。
import { fileIo } from '@kit.CoreFileKit';
const filePath = getContext(this).filesDir + '/config.json';
const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
fileIo.writeSync(file.fd, JSON.stringify({ theme: 'dark' }));
fileIo.closeSync(file);
沙盒内的文件不需要额外权限,应用卸载时也会随之清除。如果要把文件暴露给其他应用,必须走 URI 授权或系统选择器。
二、文件选择器:让用户决定存到哪
应用不应该直接操作用户相册、下载目录里的文件。鸿蒙提供了系统级选择器,由用户主动选择目标路径。
选择文件
import { picker } from '@kit.CoreFileKit';
async function pickFile() {
const documentPicker = new picker.DocumentViewPicker();
const result = await documentPicker.select({
maxSelectNumber: 1,
defaultFilePathAreas: [picker.DLFilePathArea.DL_DOWNLOAD],
});
console.info(`选中文件:${result[0]}`);
}
保存文件
async function saveFile() {
const documentPicker = new picker.DocumentViewPicker();
const result = await documentPicker.save({
newFileNames: ['report.txt'],
});
// 系统返回授权后的 URI,应用可写入
const uri = result[0];
const file = fileIo.openSync(uri, fileIo.OpenMode.WRITE_ONLY);
fileIo.writeSync(file.fd, '这是一份报告');
fileIo.closeSync(file);
}
选择器返回的是 file:// 格式的 URI,通常带有临时授权。应用不需要申请存储权限,只要在返回的 URI 上操作即可。
三、PhotoPicker 与 MediaLibrary
图片和视频有专门的选择器:
import { picker } from '@kit.CoreFileKit';
async function pickPhoto() {
const photoPicker = new picker.PhotoViewPicker();
const result = await photoPicker.select({
MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE,
maxSelectNumber: 9,
});
console.info(`选中 ${result.photoUris.length} 张图片`);
}
如果需要更复杂的媒体操作,比如读取相册元数据、批量管理,可以使用 @kit.MediaLibraryKit。但要注意:媒体库操作涉及用户隐私,必须在 module.json5 中声明权限,并在运行时申请。
四、跨应用文件共享:URI 授权
如果 A 应用想把自己的文件分享给 B 应用,不能直接传路径,因为 B 没有权限访问 A 的沙盒。正确做法是:A 生成一个带权限的 File URI,通过 Want 传递。
import { fileUri } from '@kit.CoreFileKit';
import { Want } from '@kit.AbilityKit';
const filePath = getContext(this).filesDir + '/shared.pdf';
const uri = fileUri.getUriFromPath(filePath);
const want: Want = {
action: 'ohos.want.action.viewData',
uri: uri,
flags: wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION,
};
B 应用收到 Want 后,可以在授权范围内读取该 URI。权限是临时的,应用退出后自动回收。这个机制和 Android 的 FileProvider 类似,但 API 更简洁。
五、实战:日志导出功能
假设应用要把最近 7 天的日志打包成 .zip 让用户保存:
在
cacheDir下创建临时 zip 文件。把
filesDir/log/下的日志文件写入 zip。调用
DocumentViewPicker.save()让用户选择保存位置。写入后删除临时文件。
注意:不要把敏感日志直接保存到公共目录。导出前应该做脱敏处理,比如去掉用户 ID、Token 等信息。
小结
鸿蒙文件管理的核心就一句话:应用只对自己的沙盒有绝对控制权,访问用户文件必须经由系统选择器或 URI 授权。
私有数据 →
filesDir/cacheDir。用户主动选择 →
DocumentViewPicker/PhotoViewPicker。跨应用共享 → 生成授权 URI,通过 Want 传递。
下一篇进入硬件连接层,先聊蓝牙与 NFC 的近场通信实战。