fluffy-oss-sdk
v0.3.1
Published
Fluffy OSS upload client SDK — upload files with signature auth and progress tracking
Maintainers
Readme
fluffy-oss-sdk
Fluffy OSS 文件上传客户端 SDK。签名认证、上传进度、UniApp App-Plus 原生上传适配,内置纯 JS 同步签名通道——App 端无需任何外部 crypto 垫片。
API 冻结声明(0.3.0):
upload()入参、UploadProgress形态与进度回调时序、错误类集合及code/details字段、signHeaders()返回Promise<SignedHeaders>,自此版本起保持不变;调用侧代码升级到 0.3.0 后不再需要跟随 SDK 变动。
安装
npm install fluffy-oss-sdk@^0.3.0如果需要在 Node.js 中获取上传进度,请额外安装可选的 Axios 依赖:
npm install axios快速开始
import { FluffyOssClient } from 'fluffy-oss-sdk'
const client = new FluffyOssClient({
baseUrl: 'https://your-backend.example/api',
appId: 'your-app-id',
secret: 'your-app-secret',
})
const result = await client.upload(file, {
applicationId: '1',
onProgress: ({ percent }) => console.log(`${percent}%`),
})运行环境与传输方式
SDK 同时服务 H5(浏览器)、Node.js 与 UniApp,运行时由交叉验证自动判定(uni.uploadFile 且无 window → uniapp;process.versions.node 且无 window/uni → node;有 window → browser;H5 版 uni-app 暴露 uni + window,正确识别为 browser)。
| 运行环境 | 输入类型 | 上传方式 |
| --- | --- | --- |
| 浏览器(含 H5) | File | 需要进度时 XMLHttpRequest,否则 fetch |
| Node.js | Buffer、Uint8Array 或本地文件路径 | fetch;Axios 可提供上传进度 |
| UniApp App-Plus | 非空本地临时文件路径字符串 | adapterUni: true 时优先 plus.uploader,缺失时回退 uni.uploadFile |
UniApp App-Plus
仅在真正的 App-Plus 构建中启用 adapterUni,并将选择器返回的本地文件路径原样传入:
const client = new FluffyOssClient({
baseUrl: 'https://your-backend.example/api',
appId: 'your-app-id',
secret: 'your-app-secret',
adapterUni: true,
})
const result = await client.upload(tempFilePath, {
applicationId: '1',
timeout: 60_000,
onProgress: ({ percent, loaded, total }) => console.log(`${percent}%`),
})原生上传会提交 file、applicationId 和可选的 callbackUrl 字段;filename 和 mime 参数在原生上传中被忽略。适配器拒绝非字符串或空白路径,不会回退到浏览器或 Node.js 上传方式。
传输分层:
plus.uploader.createUpload(主路径,App-Plus 必然可用):监听底层任务态(statechanged),完成回调携带 HTTP 状态码与响应文本,提供字节级uploadedSize/totalSize进度,abort()对接超时与AbortSignal。原生超时始终显式设置(调用方timeout毫秒换算为秒;未传时取规范默认 120 秒),不受 app-service JS 挂起影响。已知限制:Android 端不开启分块时原生进度会失真(可能从 0 直接跳到完成);本后端为普通 multipart POST 不支持分块,故进度粒度受限,但任务态与完成信号不受影响。uni.uploadFile(降级路径,plus 缺失时):透传timeout参数(社区标注 App 2.10.0+ 支持,请真机验证一次),并特性检测task.onStateChange(非标准 API,仅显式fail态终止上传)。无论是否传参,App 端 manifest.json 的networkTimeout.uploadFile(默认 60000ms,HBuilderX 2.5.10+)在原生层始终生效。
SDK 永不自动重试上传:重试 multipart 请求可能导致服务端创建重复任务;plus.uploader 的默认重试(3 次)被显式固定为 0。
watchdog 配置
const client = new FluffyOssClient({ ..., adapterUni: true, watchdog: 'off' })"auto"(默认):JS watchdog(setTimeout)与原生超时双层兜底。App 切后台时 JS 定时器随引擎挂起、回前台后立即补触发,因此超时错误可能晚于 wall-clock 时点抛出,但 Promise 必落定。"off":只依赖原生超时。plus.uploader有规范内置超时所以始终可用;uni.uploadFile降级路径无 SDK 可验证的原生超时,此时若也未传timeout,上传会直接抛WATCHDOG_UNAVAILABLE而不是静默悬挂。
签名通道
签名算法与后端 SignatureGuard 完全一致:secretHash = SHA-256(secret)(hex),signature = HMAC-SHA256(secretHash, appId + timestamp + nonce)(hex)。
引擎顺序:Web Crypto → 纯 JS 同步核心。
- 浏览器 / Node:优先 Web Crypto(digest 与 HMAC 各有 3 秒内部期限,超时抛
SIGN_TIMEOUT;Web Crypto 存在但损坏时静默落回纯 JS 核心)。 - UniApp(
adapterUni: true或检测为 uniapp 运行时):强制走纯 JS 同步核心,全程零 await,从根上绕开 app-service 中 Web Crypto Promise 与定时器派发的不可靠性。 - 纯 JS 核心自带 UTF-8 编码与 SHA-256/HMAC 实现,无
TextEncoder、无 Web Crypto、无 Node crypto 的裸 JS 环境同样可用(已用node:crypto验算一致性);调用侧无需再引入任何app-crypto之类的垫片。
nonce 随机源说明:优先 crypto.getRandomValues;完全缺失时降级为「时间戳 + 单调计数器 + Math.random」播种的 PRNG。nonce 在后端仅承担 Redis 一次性防重放去重职责(重复即 401,Redis 故障时跳过),且作为 HMAC 输入参与签名——可预测性不构成攻击面,唯一性才是硬要求,故该降级仅影响随机数质量、不影响签名安全;冲突后果为一次可重试的 401。H5 环境全量支持 getRandomValues,降级路径不可达。
环境自检
const report = FluffyOssClient.probe({ adapterUni: true })
// { webCrypto, textEncoder, adapter, nativeTimeout, watchdog }webCrypto / textEncoder 为能力布尔值;adapter 为判定出的运行时;nativeTimeout 在 App-Plus 主路径为 true、uni.uploadFile 降级路径为 'unknown'(需真机确认);watchdog 表示 SDK 定时器已被观测到触发(或非 uniapp 运行时)。仅用于 dev 诊断,替代调用侧手写探针与 Toast 路标。
上传选项
| 选项 | 类型 | 说明 |
| --- | --- | --- |
| applicationId | string | 目标应用 ID。为保持兼容性,默认值为 "1"。 |
| callbackUrl | string | 随上传请求发送的可选回调地址。 |
| filename | string | Node.js 上传时使用的自定义文件名。在 UniApp 中会被忽略。 |
| mime | string | Node.js 上传时使用的自定义 MIME 类型。在 UniApp 中会被忽略。 |
| onProgress | (progress: UploadProgress) => void | 上传进度回调。settled 后不再回调;App-Plus 主路径提供真实字节,uni.uploadFile 与浏览器路径为百分比 + 字节。 |
| timeout | number | 上传超时时间,单位为毫秒,必须为正数。 |
| signal | AbortSignal | 当信号被中止时取消上传。 |
错误处理
所有错误继承 FluffyOssError,携带稳定 code(0.3.0 定稿)与可选 cause / details,供 release 包(console 被剥离)下凭 Toast 文案 + code 定位:
import { FluffyOssError } from 'fluffy-oss-sdk'
try {
await client.upload(file, { applicationId: '1', timeout: 60_000 })
} catch (error) {
if (error instanceof FluffyOssError) {
console.error(error.code, error.message, error.details)
}
}| code | 含义 | 排查动作 |
| --- | --- | --- |
| SIGN_TIMEOUT | Web Crypto 签名超时(3s/步) | 运行时 Web Crypto 异常,SDK 已降级场景之外出现即上报;已自动落回纯 JS 的不受影响 |
| SIGN_UNSUPPORTED | 签名前置条件缺失(理论兜底) | 检查运行时是否极端受限 |
| API_ERROR | 服务端返回失败(status + 信封 message) | 按 HTTP 状态与后端 message 查鉴权/时间窗/签名/参数 |
| NETWORK_ERROR | 未收到可用响应 | details 含 errMsg/errno/taskState/statusCode/transport,查 DNS、TLS 证书、明文 HTTP 策略、服务端可用性 |
| UPLOAD_TIMEOUT | 超过配置的 timeout | details.timeoutMs;App 后台挂起场景会延迟到回前台抛出 |
| UPLOAD_CANCELED | AbortSignal 被中止 | 预期行为 |
| WATCHDOG_UNAVAILABLE | watchdog 关闭且无任何可确认超时层 | 传 timeout 或恢复 watchdog: 'auto' |
| INVALID_INPUT | 参数不合法(空白路径、非法 timeout 等) | 修正调用参数 |
开发命令
npm run typecheck
npm test
npm run build
npm pack --dry-run测试覆盖:NIST/RFC 向量与 node:crypto 交叉验证、裸 JS 环境签名(无 Web Crypto / 无 TextEncoder)、运行时探测矩阵、dist 产物卫生(禁止 node:crypto、Node 动态导入必须带运行时守卫)、plus/uni 双轨传输行为与黑洞场景。
