Administrator
发布于 2026-09-01 / 61 阅读
0
0

鸿蒙文件管理与文档处理:沙盒、选择器与跨应用共享

系列文章《鸿蒙开发从入门到专家》第 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 让用户保存:

  1. 在 cacheDir 下创建临时 zip 文件。

  2. 把 filesDir/log/ 下的日志文件写入 zip。

  3. 调用 DocumentViewPicker.save() 让用户选择保存位置。

  4. 写入后删除临时文件。

注意:不要把敏感日志直接保存到公共目录。导出前应该做脱敏处理,比如去掉用户 ID、Token 等信息。

小结

鸿蒙文件管理的核心就一句话:应用只对自己的沙盒有绝对控制权,访问用户文件必须经由系统选择器或 URI 授权。

  • 私有数据 → filesDir / cacheDir。

  • 用户主动选择 → DocumentViewPicker / PhotoViewPicker。

  • 跨应用共享 → 生成授权 URI,通过 Want 传递。

下一篇进入硬件连接层,先聊蓝牙与 NFC 的近场通信实战。


评论