【HarmonyOS NEXT】鸿蒙将 Resource/RawFile 资源文件复制到应用沙箱目录
一、前言
在 HarmonyOS NEXT 开发过程中,经常会遇到这样的需求:
- 第一次启动应用,将 SQLite 数据库复制到沙箱
- 将 AI 模型文件复制到沙箱
- 将 json 配置文件复制到沙箱
- 将 html/js/css 离线资源复制到沙箱
- 将字体(ttf)、视频(mp4)、音频(mp3)复制到沙箱
- 将 SVG、图片资源复制到缓存目录
- 将大文件解压到沙箱
这些文件一般都会放到:
resources/rawfile/
运行时,再复制到应用沙箱:
/data/storage/el2/base/files/
很多第三方 SDK、数据库、OCR、AI、大模型都要求文件必须是真实路径,因此掌握 RawFile → 沙箱复制十分重要。
本文将全面讲解所有实现方式、最佳实践以及性能优化。
二、为什么需要复制到沙箱?
RawFile 属于应用安装包资源。
例如:
resources
└── rawfile
├── db.db
├── config.json
├── model.bin
├── index.html
└── video.mp4
这些资源:
✅ 可以读取
但是:
❌ 无法修改
例如:
SQLite
不能直接:
resources/rawfile/db.db
因为数据库需要:
- 写权限
- 创建 WAL
- 创建 Journal
因此必须复制到:
files/db.db
之后再打开数据库。
三、RawFile 与 Media 的区别
| 类型 | Resource | RawFile | 沙箱 |
|---|---|---|---|
| 图片 | √ | √ | √ |
| 可修改 | × | × | √ |
| 获取路径 | × | × | √ |
| 可写 | × | × | √ |
| 推荐数据库 | × | × | √ |
| AI模型 | × | × | √ |
因此:
需要真实路径的文件,一律复制到沙箱。
四、RawFile 目录
项目:
entry
├── src
│ ├── main
│ │ ├── ets
│ │ ├── resources
│ │ │ └── rawfile
│ │ │ ├── db.db
│ │ │ ├── config.json
│ │ │ ├── model.bin
│ │ │ ├── font.ttf
│ │ │ └── test.txt
打包后:
HAP
安装完成:
RawFile
属于只读资源。
五、沙箱目录介绍
HarmonyOS 常用目录:
filesDir
cacheDir
preferences
database
temp
获取 Context:
let context = getContext(this) as common.UIAbilityContext;
获取目录:
context.filesDir
例如:
/data/storage/el2/base/files/
复制目标:
files/test.txt
六、读取 RawFile
导入:
import { resourceManager } from '@kit.LocalizationKit';
获取 ResourceManager:
let context = getContext(this) as common.UIAbilityContext;
let manager = context.resourceManager;
读取:
let arrayBuffer = await manager.getRawFileContent("test.txt");
返回:
ArrayBuffer
七、ArrayBuffer 写入沙箱
导入:
import fs from '@ohos.file.fs';
创建文件:
let path = context.filesDir + "/test.txt";
写入:
await fs.writeFile(path, arrayBuffer);
完成复制。
八、完整示例
import fs from '@ohos.file.fs';
async function copyRawFile(context: common.UIAbilityContext) {
const manager = context.resourceManager;
const buffer = await manager.getRawFileContent("config.json");
const target = context.filesDir + "/config.json";
await fs.writeFile(target, buffer);
console.info("复制成功");
}
九、复制数据库
例如:
rawfile
db.db
复制:
const dbBuffer = await manager.getRawFileContent("db.db");
await fs.writeFile(
context.filesDir + "/db.db",
dbBuffer
);
之后:
files/db.db
即可用于:
- RDB
- SQLite
- 第三方数据库
十、复制 JSON
const buffer =
await manager.getRawFileContent("config.json");
await fs.writeFile(
context.filesDir+"/config.json",
buffer
);
读取:
let text = fs.readTextSync(
context.filesDir+"/config.json"
);
十一、复制图片
例如:
logo.png
复制:
const image =
await manager.getRawFileContent("logo.png");
await fs.writeFile(
context.filesDir+"/logo.png",
image
);
十二、复制 SVG
例如:
icon.svg
复制:
const svg =
await manager.getRawFileContent("icon.svg");
await fs.writeFile(
context.filesDir+"/icon.svg",
svg
);
之后即可:
Image
Web
Canvas
等组件加载。
十三、复制字体
例如:
font.ttf
const font =
await manager.getRawFileContent("font.ttf");
await fs.writeFile(
context.filesDir+"/font.ttf",
font
);
十四、复制视频
例如:
video.mp4
const video =
await manager.getRawFileContent("video.mp4");
await fs.writeFile(
context.filesDir+"/video.mp4",
video
);
播放器即可使用:
file://
路径播放。
十五、复制 AI 模型
例如:
llm.bin
ocr.bin
face.bin
统一:
await fs.writeFile(
context.filesDir+"/model.bin",
buffer
);
供:
AI SDK
加载。
十六、判断是否已复制
避免重复复制:
const path =
context.filesDir+"/config.json";
let exist =
await fs.access(path);
if(!exist){
}
推荐:
第一次启动复制。
以后直接读取。
十七、封装工具类
import fs from '@ohos.file.fs';
export class RawFileUtil {
static async copy(
context: common.UIAbilityContext,
fileName: string
) {
const manager = context.resourceManager;
const buffer =
await manager.getRawFileContent(fileName);
const target =
context.filesDir + "/" + fileName;
await fs.writeFile(target, buffer);
return target;
}
}
调用:
await RawFileUtil.copy(
context,
"db.db"
);
十八、批量复制
const files = [
"db.db",
"config.json",
"model.bin",
"font.ttf"
];
for (const file of files){
await RawFileUtil.copy(
context,
file
);
}
十九、大文件复制优化
对于数十 MB 甚至数百 MB 的资源:
推荐:
RawFile Stream
不要一次性:
ArrayBuffer
全部读入。
建议:
InputStream
↓
Buffer
↓
OutputStream
边读边写,降低内存占用。
二十、异常处理
try{
await RawFileUtil.copy(
context,
"db.db"
);
}catch(err){
console.error(
JSON.stringify(err)
);
}
二十一、常见问题
1. 为什么不能直接修改 RawFile?
RawFile 属于应用安装包资源,安装后是只读的,因此不能直接写入或覆盖。
2. 为什么 SQLite 必须复制?
SQLite 会创建日志文件(如 WAL、Journal)并进行写操作,因此数据库文件必须位于应用可写的沙箱目录。
3. 为什么找不到文件?
请确认:
- 文件位于
resources/rawfile/目录; - 调用
getRawFileContent()时文件名(含扩展名)正确; - 文件已包含在构建产物中。
4. 每次启动都要复制吗?
不建议。可在首次启动或检测到目标文件不存在时复制,后续直接使用沙箱中的文件。
5. 复制到 filesDir 还是 cacheDir?
- 长期保存的数据(数据库、配置、模型等):使用
filesDir。 - 临时缓存文件(图片、下载缓存等):使用
cacheDir。
二十二、最佳实践
推荐遵循以下流程:
- 将静态资源放入
resources/rawfile/。 - 应用首次启动时检查沙箱中目标文件是否存在。
- 若不存在,则从 RawFile 复制到
filesDir。 - 后续业务统一使用沙箱中的文件路径。
- 对于大文件,优先采用流式复制,避免一次性加载到内存。
二十三、总结
resources/rawfile 是 HarmonyOS NEXT 中存放原始资源的重要目录,适合存放数据库、配置文件、AI 模型、字体、音视频等资源。但由于它属于只读区域,凡是需要真实文件路径或后续写入的场景,都应在应用启动时复制到沙箱目录(通常为 filesDir)后再使用。
实际项目中,建议封装统一的 RawFile 复制工具,结合文件存在性检查和异常处理,实现高效、安全、可维护的资源初始化流程。这也是 HarmonyOS NEXT 项目中数据库初始化、AI 模型部署、离线资源管理等场景的推荐实现方式。
更多推荐



所有评论(0)