rn-fetch-blob:基于 React Native 鸿蒙生态的文件下载与文件系统适配项目

提供文件上传下载与本地文件访问能力的网络/文件系统模块

Branch3Tags3
FilesLast commitLast update
12 days ago
12 days ago
12 days ago
1 month ago
1 month ago
12 days ago
12 days ago
12 days ago
1 month ago
12 days ago
1 month ago

rn-fetch-blob

本项目基于 rn-fetch-blob开发。如果在使用过程中有任何问题,欢迎在AtomGit提交Issue,会及时跟进。

项目介绍

@hxa-rn/rn-fetch-blob 是 rn-fetch-blob 的 React Native 鸿蒙(OpenHarmony)适配包,提供上传、下载与文件系统访问能力,支持文件流读写以处理大文件。当前版本 0.12.4。

鸿蒙适配包版本 原始库版本 支持 RN 版本 Autolink 编译 API 版本
0.12.4 0.12.0 0.72+ 是 API12+

集成指南

npm install @hxa-rn/rn-fetch-blob

peerDependencies:react-native >= 0.72。

import 时使用原库名 'rn-fetch-blob',而非鸿蒙适配包名 '@hxa-rn/rn-fetch-blob'(harmony.alias 已配置为 rn-fetch-blob)。

当前版本支持 Autolink;若工程已接入 Autolink,可跳过手动配置。

Manual Link 配置

本模块需要同时在 C++ 侧和 ETS 侧注册 Package。

1. Overrides RN SDK

在工程根目录 oh-package.json5 添加:

{
  "overrides": {
    "@rnoh/react-native-openharmony": "./react_native_openharmony"
  }
}

2. 引入原生端依赖

打开 entry/oh-package.json5,添加:

"dependencies": {
  "@hxa-rn/rn-fetch-blob": "file:../../node_modules/@hxa-rn/rn-fetch-blob/harmony/fetch_blob.har"
}

执行 ohpm install。

3. 配置 CMakeLists

打开 entry/src/main/cpp/CMakeLists.txt,添加:

set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")

add_subdirectory("${OH_MODULES}/@hxa-rn/rn-fetch-blob/src/main/cpp" ./fetch_blob)

target_link_libraries(rnoh_app PUBLIC fetch_blob)

4. 注册 Package(C++ 侧)

打开 entry/src/main/cpp/PackageProvider.cpp,添加:

#include "FetchBlobPackage.h"

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<FetchBlobPackage>(ctx),
    };
}

5. 注册 Package(ETS 侧)

打开 entry/src/main/ets/RNPackagesFactory.ets,添加:

import { FetchBlobPackage } from '@hxa-rn/rn-fetch-blob';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new FetchBlobPackage(ctx),
  ];
}

使用说明

import RNFetchBlob from 'rn-fetch-blob';

async function run() {
  // 1. HTTP 文件下载
  const resp = await RNFetchBlob.config({
    fileCache: true,
    appendExt: 'png',
    path: `${RNFetchBlob.fs.dirs.DocumentDir}/sample.png`,
    timeout: 30000,
  }).fetch('GET', 'https://picsum.photos/200/300');

  const filePath = resp.path();
  const info = resp.respInfo;
  console.log('saved to:', filePath, 'status:', info.status);

  // 2. 下载进度
  await RNFetchBlob.config({ fileCache: true })
    .fetch('GET', 'https://picsum.photos/200/300')
    .progress({ count: 1, interval: 100 }, (received, total) => {
      console.log(`received ${received} / ${total}`);
    });

  // 3. POST JSON
  await RNFetchBlob.config({})
    .fetch(
      'POST',
      'https://httpbin.org/post',
      { 'Content-Type': 'application/json' },
      JSON.stringify({ name: 'test' }),
    );

  // 4. 文件系统
  await RNFetchBlob.fs.createFile(
    `${RNFetchBlob.fs.dirs.DocumentDir}/a.txt`,
    'Hello',
    'utf8',
  );
  const content = await RNFetchBlob.fs.readFile(
    `${RNFetchBlob.fs.dirs.DocumentDir}/a.txt`,
    'utf8',
  );
  console.log('file content:', content);
  await RNFetchBlob.fs.unlink(`${RNFetchBlob.fs.dirs.DocumentDir}/a.txt`);
}

run();

平台差异:

  • 目录常量:DocumentDir / CacheDir / PictureDir / MusicDir / MovieDir / DownloadDir 映射鸿蒙应用沙箱绝对路径;DCIMDir / SDCardDir / SDCardApplicationDir / LibraryDir 鸿蒙无对应外部存储概念,降级返回 '' 或应用沙箱路径
  • 不支持 API:fs.scanFile、android.addCompleteDownload、ios.previewDocument / openDocument / excludeFromBackupKey、fs.pathForAppGroup —— 调用时 reject / callback 返回 … is not supported on HarmonyOS,业务需 try-catch(详解见下方「遗留问题」)
  • syncPathAppGroup 返回 '';emitExpiredEvent 为空实现(不列入「不支持」报告,见下方约束)
  • actionViewIntent 使用 @kit.PreviewKit 预览文件;getContentIntent 使用 @ohos.file.picker DocumentViewPicker
  • wifiOnly / trusty / followRedirect 等配置项已按鸿蒙 @ohos.net.http 语义实现

接口文档

API 描述 参数 返回值 HarmonyOS 支持
config(options) 注入请求配置(fileCache/path/timeout/appendExt 等) RNFetchBlobConfig RNFetchBlobStatic ✅
fetch(method, url, headers?, body?) 发起 HTTP 请求,支持 GET/POST/PUT/DELETE 与 multipart method, url, headers, body StatefulPromise<FetchBlobResponse> ✅
.progress(config?, cb) 下载进度上报 {count,interval}, (received,total)=>void 链式 Promise ✅
.uploadProgress(config?, cb) 上传进度上报 {count,interval}, (sent,total)=>void 链式 Promise ✅
.cancel(cb?) 取消进行中的请求 可选回调 链式 Promise ✅
.stateChange(cb) HTTP 状态变化事件(state 2 = header 就绪) (state)=>void 链式 Promise ✅
session(name) 获取/创建缓存会话 name RNFetchBlobSession ✅
fs.dirs 应用目录常量集合 - Dirs ✅
fs.createFile(path, data, encoding) 创建文本/二进制文件 path, data, encoding Promise<string> ✅
fs.createFileASCII(path, dataArray) 创建 ASCII 文件 path, number[] Promise<void> ✅
fs.readFile(path, encoding) 读取文件(utf8/base64/ascii) path, encoding Promise<string | number[]> ✅
fs.writeFile(path, data, encoding) 写入文件 path, data, encoding Promise<void> ✅
fs.appendFile(path, data, encoding) 追加内容 path, data, encoding Promise<number> ✅
fs.unlink(path) 删除文件 path Promise<void> ✅
fs.mkdir(path) 创建目录 path Promise<void> ✅
fs.exists(path) 判断路径是否存在 path Promise<boolean> ✅
fs.isDir(path) 判断是否为目录 path Promise<boolean> ✅
fs.ls(path) 列出目录内容 path Promise<string[]> ✅
fs.stat(path) 获取文件状态 path Promise<RNFetchBlobStat> ✅
fs.lstat(path) 获取符号链接状态 path Promise<RNFetchBlobStat[]> ✅
fs.cp(src, dest) 复制文件 src, dest Promise<boolean> ✅
fs.mv(src, dest) 移动文件 src, dest Promise<boolean> ✅
fs.slice(src, dest, start, end) 文件切片 src, dest, start, end Promise<void> ✅
fs.hash(path, algorithm) 计算文件哈希 path, md5/sha1/sha256 Promise<string> ✅
fs.df() 查询磁盘空间 - Promise<{free,total}> ✅
fs.writeStream(path, encoding, append) 开启写入流 path, encoding, append Promise<WriteStream> ✅
fs.writeChunk(streamId, data) 写入流数据块 streamId, data Promise<void> ✅
fs.writeArrayChunk(streamId, dataArray) 写入字节数组块 streamId, number[] Promise<void> ✅
fs.closeStream(streamId) 关闭写入流 streamId Promise<void> ✅
fs.readStream(path, encoding, bufferSize, tick) 开启读取流(data/end/error 事件) path, encoding, bufferSize, tick Promise<ReadStream> ✅
fs.removeSession(paths) 批量删除会话缓存文件 string[] Promise<void> ✅
fs.asset(path) 映射应用资源路径 path string ✅
android.actionViewIntent(path, mime) 系统文件预览 path, mime Promise<void> ✅
android.getContentIntent(mime) 内容选择器选文件 mime Promise<string> ✅
android.addCompleteDownload(config) 添加下载记录 config Promise<void> ❌ 否(U-02)
android.getSDCardDir() 获取 SD 卡目录 - Promise<string> ⚠️ 沙箱路径
android.getSDCardApplicationDir() 获取 SD 卡应用目录 - Promise<string> ⚠️ 沙箱路径
fs.scanFile(pairs) 媒体文件扫描入相册 Array<{path}> Promise<void> ❌ 否(U-01)
ios.previewDocument(uri, scheme) iOS 文档预览 uri, scheme Promise<void> ❌ 否(U-03)
ios.openDocument(uri, scheme) iOS 文档打开 uri, scheme Promise<void> ❌ 否(U-04)
ios.excludeFromBackupKey(url) iOS 排除备份 url Promise<void> ❌ 否(U-05)
fs.pathForAppGroup(group) iOS App Group 路径 group Promise<string> ❌ 否(U-06)
fs.syncPathAppGroup(group) iOS App Group 同步 group string ⚠️ 返回 ''

✅ = 鸿蒙原生实现;⚠️ = 降级/沙箱替代实现(不列入不支持报告);❌ = 鸿蒙不支持,返回 … is not supported on HarmonyOS(编号见下方「遗留问题」)。 目录常量获取方式:RNFetchBlob.fs.dirs.DocumentDir 等(getConstants() 映射)。

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 18
DevEco Studio 5.0+
HarmonyOS SDK API 12+

运行步骤

1. 克隆仓库

git clone https://gitcode.com/hxa-rn/rn-fetch-blob.git
cd rn-fetch-blob
git checkout main

2. 安装仓库开发依赖

npm install --legacy-peer-deps

Example 已改为从 npm 公仓安装 @hxa-rn/rn-fetch-blob@0.12.4,不再使用本地 file:../xxx.tgz,运行 Example 不必再执行 npm pack。

3. 进入 example 目录,安装依赖

cd example          # 或 example_auto
npm install --legacy-peer-deps

4. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

5. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio
  • 选择 example/harmony(或 example_auto/harmony)目录
  • 等待 Sync 完成

6. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备/模拟器。

注意:Example 中已预置插件依赖和 Package 注册,无需手动配置 Link。Example 已声明 ohos.permission.INTERNET(HTTP 请求必需)。

约束与限制

兼容性

  • 鸿蒙 SDK:API 12+
  • 上游 RN 库:rn-fetch-blob 0.12.0
  • React Native / RNOH:0.72+
  • DevEco Studio:5.0+

权限

  • ohos.permission.INTERNET(HTTP 请求必需,需在 entry/src/main/module.json5 的 requestPermissions 中声明)

平台能力差异

  • 大文件(GB 级)响应体按 path/fileCache 落盘,避免读入内存导致 OOM
  • wifiOnly 仅对蜂窝数据网络生效(与 Android SDK21+ 语义一致)
  • trusty 信任自签名证书场景受鸿蒙系统 CA 策略限制
  • getSDCardDir / getSDCardApplicationDir 无外部 SD 概念,返回应用 filesDir
  • syncPathAppGroup 返回空串;emitExpiredEvent 为空实现(iOS AppState 过期网络事件,鸿蒙无对等触发)

开源license

本项目基于 MIT 协议,详见 LICENSE 文件。

问题反馈渠道

使用问题请在 AtomGit 提交 Issue。也可在 GitCode 仓库反馈:

https://gitcode.com/hxa-rn/rn-fetch-blob

https://gitcode.com/hxa-rn/rn-fetch-blob/issues

Introduction

提供文件上传下载与本地文件访问能力的网络/文件系统模块

Customize your domain