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

大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
摘要
在实际的鸿蒙开发中,文件读写几乎是绕不开的一件事,比如:
- 下载 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)