HarmonyOS 文件权限管理实战详解(含可运行 Demo)
在实际的鸿蒙开发中,文件读写几乎是绕不开的一件事,比如:下载 OTA 升级包保存拍照或截图从外部导入文件设备之间同步数据文件但很多刚接触 HarmonyOS 的同学都会踩同一个坑:


大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向:前端 / 跨端 / 小程序 / 移动端工程化
内容平台:掘金、知乎、CSDN、简书
创作特点:实战导向、源码拆解、少空谈多落地
文章状态:长期稳定更新,大量原创输出
我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学“明白”,也用“到位”
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
摘要
在实际的鸿蒙开发中,文件读写几乎是绕不开的一件事,比如:
- 下载 OTA 升级包
- 保存拍照或截图
- 从外部导入文件
- 设备之间同步数据文件
但很多刚接触 HarmonyOS 的同学都会踩同一个坑:
权限明明写了,代码也没报错,但就是读不了文件。
根本原因就在于:
鸿蒙的文件权限模型,和 Android、传统 Linux 思维完全不一样。
这篇文章会从设计理念 → 权限声明 → 运行时授权 → 文件读写 → 实际场景,一步一步把鸿蒙的文件权限讲清楚,并配上可以直接运行的 Demo 代码。
引言
随着 HarmonyOS 进入多设备、分布式阶段,应用已经不只是“装在一台手机上跑”。
现在的常见场景是:
- 手机负责界面
- 平板负责编辑
- 手表负责控制
- 设备之间共享文件和数据
在这种情况下,如果文件权限没设计好,轻则功能不可用,重则直接审核不过。
鸿蒙在权限这块的思路很明确:
默认不让你乱访问
能不开放就不开放
能让系统托管的,开发者尽量别自己搞
理解了这个思想,后面的 API 用起来就会顺很多。
鸿蒙的文件权限整体模型
应用沙箱机制
在 HarmonyOS 中,每个应用都有一个完全隔离的私有目录:
/data/storage/el2/base/haps/your.bundle.name/
这个目录的特点只有一句话:
只要是你自己的应用,随便读写,不需要任何权限。
在代码里通常这样拿:
const filesDir = context.filesDir;
这里的 context 一般来自 EntryAbility。
这个目录非常适合:
- 缓存文件
- 配置文件
- OTA 升级包
- 临时数据
为什么鸿蒙强调沙箱
主要原因有三个:
- 防止应用互相乱读文件
- 防止恶意扫描用户隐私
- 方便系统统一回收和管理
所以如果你能把文件放在应用私有目录,基本可以避开 80% 的权限问题。
文件相关权限说明
在 module.json5 中声明权限
如果你需要访问公共目录或媒体文件,就必须在 module.json5 中声明权限。
示例:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.READ_MEDIA",
"reason": "需要读取用户选择的图片和视频文件",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
这里有几个点一定要注意:
reason会展示给用户看when建议用inuse- 不要乱写权限,审核会看
常见文件权限对照表
| 权限名 | 作用 |
|---|---|
| READ_MEDIA | 读取图片、视频、音频 |
| WRITE_MEDIA | 写入多媒体文件 |
| READ_USER_STORAGE | 读取用户文件 |
| WRITE_USER_STORAGE | 写入用户文件 |
实际开发中,READ_MEDIA + 文件选择器就能解决大部分问题。
运行时权限申请流程
在鸿蒙中,声明权限 ≠ 已经授权。
真正能不能用,取决于运行时。
检查权限是否已经授权
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
const atManager = abilityAccessCtrl.createAtManager();
async function checkPermission(context) {
const result = await atManager.checkAccessToken(
context.applicationInfo.accessTokenId,
'ohos.permission.READ_MEDIA'
);
return result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
这一步一般在真正读文件之前做,而不是一启动就做。
向用户申请权限
async function requestPermission(context) {
await atManager.requestPermissionsFromUser(
context,
['ohos.permission.READ_MEDIA']
);
}
如果用户拒绝了,你的代码必须能兜底,比如:
- 弹提示
- 关闭相关功能
- 引导用户重新授权
文件读写 Demo
应用私有目录文件读写(无需权限)
import fs from '@ohos.file.fs';
function writePrivateFile(context) {
const filePath = context.filesDir + '/demo.txt';
const file = fs.openSync(
filePath,
fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE
);
fs.writeSync(file.fd, 'Hello HarmonyOS');
fs.closeSync(file);
}
这段代码在任何设备上都能直接跑。
适合用在:
- 升级包缓存
- 日志文件
- 本地配置
访问公共媒体文件(需要权限)
import fs from '@ohos.file.fs';
function readPublicFile() {
const uri = 'file://media/Photo/test.jpg';
const file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
fs.closeSync(file);
}
如果你没申请权限,这里会直接失败。
实际应用场景分析
场景一:OTA 升级包管理
推荐方案:
- 下载到应用私有目录
- 不走公共存储
- 不申请任何文件权限
示例代码:
function getUpgradePath(context) {
return context.filesDir + '/upgrade/update.bin';
}
这样做的好处是:
- 权限最少
- 风险最低
- 稳定性最高
场景二:用户手动导入文件
这种情况最推荐用文件选择器。
import picker from '@ohos.file.picker';
async function selectFile() {
const photoPicker = new picker.PhotoViewPicker();
const result = await photoPicker.select();
console.info('用户选择的文件:', JSON.stringify(result));
}
系统会自动处理权限弹窗,你只拿结果。
场景三:分布式设备间文件同步
思路很简单:
- 文件先放私有目录
- 用分布式能力同步
- 不直接访问对方文件系统
示例路径统一:
const syncDir = context.filesDir + '/distributed/';
这样可以保证:
- 每台设备都有独立沙箱
- 不破坏系统安全模型
QA 常见问题
Q1:为什么我申请了权限还是读不到文件?
通常原因有三种:
- URI 写错
- 权限申请时机不对
- 用户拒绝了授权
建议在代码里明确判断授权结果。
Q2:能不能一上来就申请所有权限?
不建议。
鸿蒙审核更看重最小权限原则,乱申请容易被打回。
Q3:文件路径能不能硬编码?
不建议。
不同设备、系统版本路径可能不一样,优先用 context.filesDir。
总结
在 HarmonyOS 中,文件权限的核心可以总结为一句话:
能用私有目录就别碰公共目录
能让系统管权限就别自己折腾
只要你记住这几个原则:
- 私有目录优先
- 权限按需申请
- 文件选择器优先
- 拒绝场景必须兜底
文件权限这一块,基本就不会再踩大坑。
更多推荐




所有评论(0)