@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 方法及上传请求头;允许的请求头可设置为 *。
