npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-huawei-obs

v0.2.0

Published

React Native SDK for Huawei Cloud OBS with multipart upload support

Readme

react-native-huawei-obs

华为云 OBS (对象存储服务) React Native SDK。支持文件上传(自动分片)、下载、删除,提供完整的进度回调和任务控制。

底层 SDK 版本

| 平台 | SDK | 版本 | |---|---|---| | Android | esdk-obs-android | 3.25.4 | | iOS | esdk-obs-ios | 3.25.6 |

安装

npm install react-native-huawei-obs
# 或
yarn add react-native-huawei-obs

iOS

cd ios && pod install

快速开始

import { OBSClient } from 'react-native-huawei-obs';

const client = new OBSClient({
  endpoint: 'obs.cn-north-4.myhuaweicloud.com',
  bucket: 'my-bucket',
  accessKeyId: 'your-ak',
  secretAccessKey: 'your-sk',
  securityToken: 'sts-token',       // STS 临时凭证(可选)
  tokenExpiryTime: 1700000000000,   // 过期时间戳 ms(可选)
});

// 等待初始化完成
await client.ready();

API

构造函数

new OBSClient(config: OBSClientConfig)

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | endpoint | string | ✅ | OBS 服务端点,如 obs.cn-north-4.myhuaweicloud.com | | bucket | string | ✅ | 桶名 | | accessKeyId | string | ✅ | 访问密钥 ID (AK) | | secretAccessKey | string | ✅ | 访问密钥 (SK) | | securityToken | string | - | STS 安全令牌 | | tokenExpiryTime | number | - | 令牌过期时间戳 (ms) | | region | string | - | 区域,如 cn-north-4 | | connectionTimeout | number | - | 连接超时(秒),默认 60 | | socketTimeout | number | - | Socket 超时(秒),默认 60 | | maxErrorRetry | number | - | 最大重试次数,默认 3 | | isHttps | boolean | - | 是否启用 HTTPS,默认 true | | pathStyle | boolean | - | 使用路径样式访问,默认 false | | maxConcurrency | number | - | 全局并发上限 1-10,默认 6 | | defaultPartSize | number | - | 默认分片大小(字节),默认自适应 | | customDomain | string | - | 自定义域名,用于上传后 URL 拼接 | | keyPrefix | string | - | 对象键前缀,如 "avatar""chat/images",自动加到所有操作的 objectKey 前 |


client.ready(): Promise<void>

等待原生客户端初始化完成。

await client.ready();

上传

client.upload(filePath, objectKey, options?): TaskHandle<UploadResult>

上传文件,自动判断使用普通上传(≤5MB)或分片上传(>5MB)。

const handle = client.upload(
  'content://...', // 或 'file:///path/to/file.mp4'
  'videos/my-video.mp4',
  {
    onPreparing: (copyProgress) => {
      // content:// 文件复制进度 (0 ~ 100 整数)
      console.log(`准备中: ${copyProgress}%`);
    },
    onStart: (taskId) => {
      console.log('上传开始, taskId:', taskId);
    },
    onProgress: (progress) => {
      console.log(`进度: ${progress.percentage}%`);
    },
    onSuccess: (result) => {
      console.log('上传成功:', result.objectUrl);
    },
    onError: (error) => {
      console.error('上传失败:', error.code, error.message);
    },
  }
);

参数:

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | filePath | string | ✅ | 文件路径,支持 file://content://、绝对路径 | | objectKey | string | ✅ | 对象键名(OBS 中的路径) | | options | UploadOptions | - | 上传选项 |

UploadOptions

| 字段 | 类型 | 说明 | |---|---|---| | contentType | string | MIME 类型,默认根据扩展名自动识别 | | metadata | Record<string, string> | 自定义元数据 | | storageClass | 'STANDARD' \| 'WARM' \| 'COLD' | 存储类型 | | acl | 'private' \| 'public-read' \| 'public-read-write' | ACL 权限 | | onPreparing | (copyProgress: number) => void | 文件准备进度(content:// 复制) | | onStart | (taskId: string) => void | 上传开始 | | onProgress | (progress: UploadProgress) => void | 上传进度 | | onSuccess | (result: UploadResult) => void | 上传成功 | | onError | (error: OBSError) => void | 上传失败 |

返回:TaskHandle<UploadResult>


分片上传

client.multipartUpload(filePath, objectKey, options?): TaskHandle<UploadResult>

upload 相同,额外支持指定分片大小和并发数。

额外 MultipartUploadOptions

| 字段 | 类型 | 说明 | |---|---|---| | partSize | number | 分片大小(字节),范围 5MB-5GB,默认自适应 | | concurrency | number | 并发上传数 1-10,默认 6 | | onCancel | (taskId: string) => void | 取消回调 |

分片自适应策略:

| 文件大小 | 分片大小 | |---|---| | < 500MB | 5MB | | ≥ 500MB | 10MB |


下载

client.download(objectKey, savePath, options?): TaskHandle<DownloadResult>

const handle = client.download(
  'videos/my-video.mp4',
  '/path/to/save/video.mp4',
  {
    onProgress: (progress) => {
      console.log(`下载: ${progress.percentage}%`);
    },
    onSuccess: (result) => {
      console.log('下载完成:', result.savePath);
    },
    onError: (error) => {
      console.error('下载失败:', error.code);
    },
  }
);

DownloadOptions

| 字段 | 类型 | 说明 | |---|---|---| | range | string | 下载范围,如 "bytes=0-1023" | | versionId | string | 版本 ID | | partSize | number | 分片大小(字节) | | concurrency | number | 并发数 1-10 | | onProgress | (progress: DownloadProgress) => void | 下载进度 | | onSuccess | (result: DownloadResult) => void | 下载成功 | | onError | (error: OBSError) => void | 下载失败 |


删除

client.deleteObject(objectKey): Promise<void>

await client.deleteObject('videos/my-video.mp4');

client.deleteObjects(objectKeys): Promise<DeleteResult[]>

const results = await client.deleteObjects([
  'videos/a.mp4',
  'videos/b.mp4',
]);

任务控制

TaskHandle 方法

const handle = client.upload(filePath, objectKey, options);

// 取消任务
await handle.cancel();

// 等待任务完成(Promise)
const result = await handle.promise();

// 链式监听
handle
  .onPreparing((copyProgress) => { ... })
  .onProgress((progress) => { ... })
  .onSuccess((result) => { ... })
  .onError((error) => { ... });

// 移除监听
handle.removeAllListeners();

全局事件

// 订阅
client.on('uploadProgress', (progress) => { ... });
client.on('uploadSuccess', (result) => { ... });
client.on('uploadError', (error) => { ... });
client.on('uploadCancel', (taskId) => { ... });

// 取消订阅
client.off('uploadProgress', listener);

// 一次性订阅
client.once('uploadSuccess', (result) => { ... });

所有事件名:

| 事件名 | 触发数据 | 说明 | |---|---|---| | uploadPreparing | { taskId, objectKey, copyProgress } | 文件准备中(content:// 复制) | | uploadStart | { taskId, objectKey, totalBytes } | 上传开始 | | uploadProgress | UploadProgress | 上传进度 | | uploadSuccess | UploadResult | 上传成功 | | uploadError | OBSError | 上传失败 | | uploadCancel | taskId: string | 上传取消 | | downloadStart | { taskId, objectKey, totalBytes } | 下载开始 | | downloadProgress | DownloadProgress | 下载进度 | | downloadSuccess | DownloadResult | 下载成功 | | downloadError | OBSError | 下载失败 | | downloadCancel | taskId: string | 下载取消 |


其他方法

// 更新配置(如刷新 STS 凭证)
await client.updateConfig({
  accessKeyId: 'new-ak',
  secretAccessKey: 'new-sk',
  securityToken: 'new-token',
  tokenExpiryTime: Date.now() + 3600000,
});

// 验证配置有效性
const isValid = await client.validateConfig();

// 获取脱敏配置
const config = client.getConfig();

// 获取所有任务
const tasks = await client.getAllTasks();

// 清除已完成任务
await client.clearCompletedTasks();

// 销毁客户端
await client.destroy();

回调数据结构

UploadProgress — 上传进度

{
  taskId: string;           // 任务 ID
  transferredBytes: number; // 已传输字节数
  totalBytes: number;       // 总字节数
  percentage: number;       // 进度 0 ~ 100 整数
  currentPart?: number;     // 当前分片号
  totalParts?: number;      // 总分片数
  completedParts?: number;  // 已完成分片数
  instantSpeed?: number;    // 瞬时速度(字节/秒)
  avgSpeed?: number;        // 平均速度(字节/秒)
  remainingTime?: number;   // 预计剩余时间(秒)
}

UploadResult — 上传结果

{
  taskId: string;      // 任务 ID
  objectKey: string;   // 对象键名
  bucket: string;      // 桶名
  etag: string;        // ETag 校验值
  versionId?: string;  // 版本 ID(桶开启版本控制时返回)
  objectUrl: string;   // 访问 URL(支持 customDomain 替换)
  size: number;        // 文件大小(字节)
  duration: number;    // 上传耗时(毫秒)
  avgSpeed: number;    // 平均速度(字节/秒)
}

DownloadProgress — 下载进度

{
  taskId: string;           // 任务 ID
  downloadedBytes: number;  // 已下载字节数
  totalBytes: number;       // 总字节数
  percentage: number;       // 进度 0 ~ 100 整数
  instantSpeed?: number;    // 瞬时速度(字节/秒)
  avgSpeed?: number;        // 平均速度(字节/秒)
  remainingTime?: number;   // 预计剩余时间(秒)
}

DownloadResult — 下载结果

{
  taskId: string;      // 任务 ID
  objectKey: string;   // 对象键名
  savePath: string;    // 本地保存路径
  size: number;        // 文件大小(字节)
  etag: string;        // ETag
  duration: number;    // 下载耗时(毫秒)
  avgSpeed: number;    // 平均速度(字节/秒)
}

DeleteResult — 删除结果

{
  objectKey: string;       // 对象键名
  success: boolean;        // 是否成功
  errorCode?: string;      // 错误码(失败时)
  errorMessage?: string;   // 错误信息(失败时)
  versionId?: string;      // 版本 ID
}

OBSError — 错误对象

{
  code: string;            // 错误码(见下方错误码表)
  message: string;         // 错误描述
  statusCode?: number;     // HTTP 状态码
  requestId?: string;      // 请求 ID
  hostId?: string;         // 主机 ID
  isRetryable: boolean;    // 是否可重试
}

错误码

SDK 错误码

| 错误码 | 说明 | |---|---| | E_UNKNOWN | 未知错误 | | E_INVALID_ARGUMENT | 参数无效 | | E_NOT_IMPLEMENTED | 功能未实现 |

鉴权错误

| 错误码 | 说明 | |---|---| | E_AUTH_INVALID_CREDENTIAL | 凭证无效(AK/SK 错误、Token 格式错误) | | E_AUTH_EXPIRED | 凭证已过期 | | E_AUTH_SIGN_FAILED | 签名失败 | | E_AUTH_PERMISSION_DENIED | 权限不足 | | E_AUTH_ACCESS_DENIED | 访问被拒绝(OBS 服务端 AccessDenied) | | E_AUTH_SIGNATURE_MISMATCH | 签名不匹配(SignatureDoesNotMatch) |

网络错误

| 错误码 | 说明 | |---|---| | E_NETWORK_TIMEOUT | 连接超时 | | E_NETWORK_ERROR | 网络错误 | | E_NETWORK_UNAVAILABLE | 网络不可用 |

文件错误

| 错误码 | 说明 | |---|---| | E_FILE_NOT_FOUND | 文件不存在 | | E_FILE_NOT_READABLE | 文件不可读 | | E_FILE_WRITE_ERROR | 文件写入失败 |

桶/资源错误

| 错误码 | 说明 | |---|---| | E_BUCKET_NOT_FOUND | 桶不存在(NoSuchBucket) |

HTTP 错误

| 错误码 | 说明 | |---|---| | E_HTTP_4XX | 4xx 客户端错误 | | E_HTTP_5XX | 5xx 服务端错误 |

流管理错误

| 错误码 | 说明 | |---|---| | E_STREAM_NOT_FOUND | 文件流不存在 | | E_STREAM_CLOSED | 文件流已关闭 | | E_INVALID_OFFSET | 无效的偏移量 | | E_READ_ERROR | 读取错误 |

上传错误

| 错误码 | 说明 | |---|---| | E_UPLOAD_INIT_FAILED | 初始化分片上传失败 | | E_UPLOAD_PART_FAILED | 分片上传失败 | | E_UPLOAD_COMPLETE_FAILED | 完成分片上传失败 | | E_UPLOAD_ABORTED | 上传已中止 | | E_UPLOAD_NOT_FOUND | 上传任务不存在(NoSuchUpload) |

下载错误

| 错误码 | 说明 | |---|---| | E_DOWNLOAD_FAILED | 下载失败 |

任务错误

| 错误码 | 说明 | |---|---| | E_TASK_NOT_FOUND | 任务不存在 | | E_TASK_CANCELED | 任务已取消 | | E_CANCELLED | 任务已被取消 |

并发错误

| 错误码 | 说明 | |---|---| | E_CONCURRENCY_LIMIT_EXCEEDED | 超过并发上限 | | E_MEMORY_INSUFFICIENT | 内存不足 |


完整示例

import { OBSClient } from 'react-native-huawei-obs';
import { pick } from '@react-native-documents/picker';

// 1. 创建客户端
const client = new OBSClient({
  endpoint: 'obs.cn-north-4.myhuaweicloud.com',
  bucket: 'my-bucket',
  accessKeyId: 'AK',
  secretAccessKey: 'SK',
  securityToken: 'STS_TOKEN',
  customDomain: 'cdn.example.com',
  keyPrefix: 'avatar', // 上传到 avatar/ 目录下
});

// 2. 等待初始化
await client.ready();

// 3. 选择并上传文件
const [file] = await pick({ type: ['*/*'] });

const handle = client.upload(file.uri, `uploads/${file.name}`, {
  onPreparing: (p) => console.log(`准备: ${p}%`),
  onProgress: (p) => console.log(`上传: ${p.percentage}%`),
  onSuccess: (r) => console.log('URL:', r.objectUrl),
  onError: (e) => console.error(e.code, e.message),
});

// 4. 可随时取消
// await handle.cancel();

// 5. 或等待完成
const result = await handle.promise();
console.log('上传完成:', result);

// 6. 销毁
await client.destroy();

License

MIT