一、前言

在 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

二十二、最佳实践

推荐遵循以下流程:

  1. 将静态资源放入 resources/rawfile/
  2. 应用首次启动时检查沙箱中目标文件是否存在。
  3. 若不存在,则从 RawFile 复制到 filesDir
  4. 后续业务统一使用沙箱中的文件路径。
  5. 对于大文件,优先采用流式复制,避免一次性加载到内存。

二十三、总结

resources/rawfile 是 HarmonyOS NEXT 中存放原始资源的重要目录,适合存放数据库、配置文件、AI 模型、字体、音视频等资源。但由于它属于只读区域,凡是需要真实文件路径或后续写入的场景,都应在应用启动时复制到沙箱目录(通常为 filesDir)后再使用。

实际项目中,建议封装统一的 RawFile 复制工具,结合文件存在性检查和异常处理,实现高效、安全、可维护的资源初始化流程。这也是 HarmonyOS NEXT 项目中数据库初始化、AI 模型部署、离线资源管理等场景的推荐实现方式。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐