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

@bnfe/obs-upload

v1.0.4

Published

华为云 OBS 浏览器文件上传

Readme

@bnfe/obs-upload

安装

pnpm add @bnfe/obs-upload

使用

浏览器工程通过包名导入,module 和 browser 均指向 ESM 入口。通过 script 标签使用时,加载 dist/obs-upload.umd.js 以及其外部依赖。

import { HwOss } from "@bnfe/obs-upload";

const hwOss = new HwOss({
  dir: "/test-upload",
  reqUrl: "/api/obs/token"
});

export const OssUpload = async (file: File, childDir = "") => {
  const result = await hwOss.upload(file, childDir);
  return result.cdnUrl;
};

临时凭证接口

reqUrl 支持绝对地址和浏览器中的相对地址。请求使用 GET,添加 expire 查询参数(单位秒,默认 3600),保留已有查询参数。 服务端返回以下 JSON;AK、SK 和 token 应为同一组临时凭证。

{
  "data": {
    "host": "https://cdn.example.com",
    "endpoint": "https://obs.xxx.myhuaweicloud.com",
    "region": "xxx",
    "bucket": "example-bucket",
    "accessKeyId": "临时 AK",
    "accessKeySecret": "临时 SK",
    "stsToken": "临时 securitytoken",
    "expiration": "2026-10-15T10:00:00Z"
  }
}

host 为文件访问域名,可以是 CDN 域名或 OBS 桶域名。endpoint 为必填的区域 OBS Endpoint(包含协议,不包含桶名)。 临时 token 支持 stsToken 和 securityToken,两者同时存在时优先使用 securityToken。region 为可选区域信息。 expiration 可选,为 ISO8601 过期时间;省略时按获取时间加 expire 计算。 每次上传前检查凭证有效期,临近过期时重新获取;同时发起的凭证请求合并为一次。 长时间上传期间如果凭证失效,可以获取新凭证后使用 checkpoint 重试分片上传。

构造参数

| 参数 | 说明 | 默认值 | | ----------------------- | ---------------------------- | ------------------- | | reqUrl | 临时凭证接口,必填 | — | | dir | 文件目录,可带首尾斜杠 | public | | expire | 请求临时凭证的有效期,单位秒 | 3600 | | multipartUploadSize | 自动分片阈值,单位字节 | 100 * 1024 * 1024 | | multipartUploadParams | 默认分片参数 | {} |

上传方法

hwOss.upload(file, childDir?, multipartUploadParams?);
hwOss.directUpload(file, childDir?);
hwOss.multipartUpload(file, childDir?, multipartUploadParams?);
hwOss.getToken(init?);

upload 对超过阈值、超过直接上传的 5GB 上限或带 checkpoint 的请求使用分片上传,其余使用直接上传。 直接上传最大 5GB;小于 100KB 且无 checkpoint 的分片请求使用直接上传。 分片上传由 SDK 的 uploadFile 完成初始化、分段上传和合并;最多 10000 段,每段最大 5GB,SDK 会按文件大小调整分段大小。 直接调用 directUpload 或 multipartUpload 也会获取临时凭证。

文件名格式为 hw-oss-web/{dir}/{childDir}/YYYYMMDDHHMMSS_随机ID.扩展名,扩展名保留字母和数字并转换为小写。 目录以 / 连接,对象 Key 不带开头的 /,返回的访问 URL 对路径段进行编码。

分片参数和断点续传

| 参数 | 说明 | 默认值 | | ---------------- | --------------------------------------------------------------------- | ------------- | | parallel | 最大并发数,正整数,对应 TaskNum | 5 | | partSize | 分片大小,100KB~5GB,单位字节,对应 PartSize | 1024 * 1024 | | checkpoint | 华为云 SDK 原始断点对象,对应 UploadCheckpoint | — | | progress | (p, fileUrl, checkpoint, res),p 为 0~1 比例,fileUrl 为 CDN URL | — | | resumeCallback | (hook, checkpoint),hook.cancel() 暂停,hook.abort() 取消并删除分段 | — | | eventCallback | (eventType, eventParams, result),华为云原始上传事件 | — |

方法参数会覆盖构造函数中的同名分片参数。断点仅可用于相同文件、相同 OBS 桶;重试保持原对象 Key。 progress 会在获得断点、传输进度变化、分段成功以及合并成功时调用,res 为最近的分段/合并响应,首次可能为 undefined。 续传开始时,初始进度按断点中已完成分片的总字节数计算;未完成分片的传输进度不计入初始值。 传输比例达到 1 时可能仍在合并分段,请以 upload Promise 成功返回为准。

import {
  HwOss,
  type UploadCheckpointTypes,
  type ResumeHookTypes
} from "@bnfe/obs-upload";

const hwOss = new HwOss({ reqUrl: "/api/obs/token" });
let checkpoint: UploadCheckpointTypes | undefined;
let hook: ResumeHookTypes | undefined;

const upload = (file: File) =>
  hwOss.multipartUpload(file, "", {
    checkpoint,
    resumeCallback: (resumeHook, cp) => {
      hook = resumeHook;
      checkpoint = cp;
    },
    progress: (p, fileUrl, cp) => {
      checkpoint = cp;
      console.log(p, fileUrl);
    }
  });

// await upload(file);
// hook?.cancel(); // 暂停时 upload 的 Promise 会 reject,调用方需要捕获。
// await upload(file); // 使用同一文件和保存的断点继续。
// checkpoint = undefined; // 上传成功后清理断点,再开始下一次上传。

断点对象包含 File 引用及 SDK 校验字段,建议在当前页面内保存原始对象,不要用阿里云的 checkpoint,也不要自行修改字段。

返回值

type ResParamsTypes = {
  cdnUrl: string; // CDN 文件访问 URL
  ossUrl: string; // 完整 OBS URL;Location 为相对路径或缺失时使用桶 Endpoint URL
  fileName: string; // 完整对象 Key
  ossResParams: any; // 华为云 SDK 原始响应
};

凭证请求失败、SDK 网络错误和非 2xx OBS 响应均会 reject。OBS 状态错误的 Error 对象包含 ossResParams 原始响应。

构建

pnpm --filter @bnfe/obs-upload build

输出 CJS、ESM、UMD 和 TypeScript 声明。与参考包一致,SDK 和 nanoid 为外部依赖;通过 script 使用 UMD 时需先提供全局 ObsClient 和 nanoid,然后访问 HwOss.HwOss。

OBS 配置与参考文档

浏览器跨域上传需要桶配置对应来源的 CORS 规则,并将 ETag 添加到暴露的响应头,使 SDK 可以读取分段 ETag 完成合并。

客户端固定使用 OBS 签名,关闭签名版本协商,不发起 ?apiversion 探测。桶的 CORS 仍需允许实际页面来源(设置为*)、PUT、GET、POST、DELETE、HEAD 方法及上传请求头;允许的请求头可设置为 *。