kj-uploader-service
v0.1.14
Published
前端可复用的文件上传服务,支持COS高级上传、STS签名、并发控制及控制方法
Readme
kj-uploader-service 使用文档(中文)
本服务提供浏览器端文件上传到腾讯云 COS 的封装,支持:
- STS 临时密钥自动获取与到期前刷新
- 高级上传(简单/分片自动选择)、并发队列与失败自动重试
- 暂停、继续、取消、按 key 重试
- 获取带签名的下载链接
- 媒体截帧:获取快照访问 URL 与快照图片内容
安装与引入
- 依赖:
cos-js-sdk-v5、blueimp-md5(作为 peerDependencies) - 方式:直接引入源码或打包后的
dist
import { FileUploader, triggerDownload, triggerDownloadBatch } from 'kj-uploader-service'构造与配置
使用 new FileUploader(config) 创建实例。
配置 UploaderConfig:
| 字段 | 类型 | 必填 | 说明 |
| ------------------ | ---------------------------------------- | ---- | ---------------------------------------------------- |
| apiEndpoint | string | 是 | STS 接口地址(服务端提供临时密钥) |
| appCode | string | 是 | 业务标识(服务端使用) |
| maxConcurrent | number | 否 | 最大并发上传数,默认 3 |
| chunkSize | number | 否 | 分片大小(字节),默认 5MB |
| retryTimes | number | 否 | 失败自动重试次数,默认 2 |
| prefixOverride | string | 否 | 上传前缀覆盖(非空生效,否则回退后端前缀) |
| stsHeaders | Record<string,string> | 否 | 仅用于 STS 接口的自定义请求头 |
| cosHeaders | Record<string,string> | 否 | 用于 COS 高级上传的 Headers |
| signConfig | { appKey: string; version?: string } | 否 | STS 签名配置(内置算法使用,默认 version=1.0.0) |
上传参数 UploadOptions
| 字段 | 类型 | 必填 | 说明 |
| -------------- | ---------------------------------- | ---- | ---------------------------------------------- |
| onBefore | (ctx: { key: string }) => void | 否 | 上传开始前回调,可获取即将使用的对象 key |
| onProgress | (pd: ProgressData) => void | 否 | 进度回调,见下方 ProgressData |
| signal | AbortSignal | 否 | 取消信号(本地即时取消) |
| headers | Record<string,string> | 否 | 覆盖 COS 上传时的 Headers |
| Bucket | string | 否 | 覆盖目标桶(默认使用后端返回) |
| Region | string | 否 | 覆盖地域(默认使用后端返回) |
| Key | string | 否 | 覆盖对象 Key(默认按前缀/日期/文件名自动生成) |
| SliceSize | number | 否 | 触发分片阈值(默认 5MB) |
| ChunkSize | number | 否 | 分片大小(默认取实例的 chunkSize) |
进度结构 ProgressData
| 字段 | 类型 | 说明 |
| -------------- | ---------- | ---------------------------------- |
| fileId | string | 内部任务标识(用于并发管理) |
| key | string | 对象存储 Key(用于 UI 显示与控制) |
| percentage | number | 进度百分比(0~1) |
| loaded | number | 已上传字节数 |
| total | number | 总字节数 |
媒体截帧参数 SnapshotQuery
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ----------------------------- | ---- | ------------------------------- |
| time | number | 是 | 截图时间点(秒) |
| width | number | 否 | 截图宽,默认 0 |
| height | number | 否 | 截图高,默认 0 |
| format | 'jpg' \| 'png' | 否 | 图片格式,默认 'jpg' |
| rotate | 'auto' \| 'off' | 否 | 旋转,默认 'auto' |
| mode | 'keyframe' \| 'exactframe' | 否 | 截帧方式,默认 'exactframe' |
公共方法
upload(file, opts?)
- 说明:上传单个文件(支持 File 对象或 Base64 字符串)
参数:
| 名称 | 类型 | 说明 |
| -------- | ----------------- | ------------------------------------------------------------ |
| file | File \| string | 需上传的浏览器文件对象,或 Base64 字符串(自动解析 MIME 转 Blob) |
| opts | UploadOptions | 可选配置,见上文 |
返回:
| 字段 | 类型 | 说明 |
| ------------ | ---------- | -------------------------------------- |
| key | string | 对象存储 Key |
| url | string | 带签名的访问链接(有效期默认 3600 秒) |
| metadata | any | COS 上传返回的原始数据 |
示例:
const res = await uploader.upload(file, {
onBefore: ({ key }) => console.log('key:', key),
onProgress: (pd) => console.log(pd.percentage)
})
console.log(res.url)uploadBatch(files)
- 说明:批量上传,将文件逐一入队并按并发限制执行
参数与返回:
| 名称 | 类型 | 说明 |
| --------- | ----------------------------------------------------- | ---------------------------------- |
| files | File[] | 文件列表 |
| 返回 | { cancel(fileId), pause(fileId), resume(fileId) } | 控制器,按内部 fileId 控制任务 |
cancel(key)
- 说明:按对象
key取消上传任务
| 名称 | 类型 | 说明 |
| ------- | ---------- | -------- |
| key | string | 对象 Key |
pause(key) / resume(key)
- 说明:按对象
key暂停/继续上传任务
| 名称 | 类型 | 说明 |
| ------- | ---------- | -------- |
| key | string | 对象 Key |
retryByKey(key, opts?)
- 说明:按对象
key重试上传(重置该任务的重试计数后重新执行)
| 名称 | 类型 | 说明 |
| -------- | ----------------- | -------- |
| key | string | 对象 Key |
| opts | UploadOptions | 可选配置 |
download(key, expires?)
- 说明:获取带签名的下载链接
| 名称 | 类型 | 说明 |
| ----------- | ---------- | ----------------------------- |
| key | string | 对象 Key |
| expires | number | 链接有效期秒数,默认 3600 |
返回:Promise<string>
downloadObject(key, opts?)
- 说明:下载对象的二进制内容(支持限速与进度)
参数:
| 名称 | 类型 | 说明 |
| -------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- |
| key | string | 对象 Key |
| opts | { Bucket?: string; Region?: string; headers?: Record<string,string>; trafficLimit?: number; onProgress?: (pd:any)=>void } | 可选配置 |
返回:Promise<Blob | ArrayBuffer>
说明:如需限速,设置 trafficLimit(bit/s),范围 819200 - 838860800;或在 headers 中传入 x-cos-traffic-limit。
示例:
// 限速 800Kb/s 下载对象内容
const body = await uploader.downloadObject('1.jpg', { trafficLimit: 819200, onProgress: (pd) => console.log(pd.percent) })
const objectUrl = URL.createObjectURL(body as Blob)triggerDownload(url, fileName?)
- 说明:触发浏览器下载(自动拼接
response-content-disposition参数) - 备注:此方法也可直接从包中引入使用,无需实例化
FileUploader。
| 名称 | 类型 | 说明 |
| ---------- | -------- | ---------------- |
| url | string | 文件的访问 URL |
| fileName | string | 下载时的保存文件名 |
triggerDownloadBatch(files, interval?)
- 说明:批量触发下载,内置间隔延迟以避免浏览器拦截
- 备注:此方法也可直接从包中引入使用,无需实例化
FileUploader。
| 名称 | 类型 | 说明 |
| ---------- | ----------------------------------------- | ---------------------------------- |
| files | { url: string; fileName?: string }[] | 文件列表 |
| interval | number | 两次下载间的延迟(毫秒),默认 1000 |
snapshotUrl(key, query, opts?)
- 说明:生成媒体截帧访问 URL(带签名与查询参数)
参数:
| 名称 | 类型 | 说明 |
| --------- | ---------------------------------------------------------- | ----------------------- |
| key | string | 媒体文件对象 Key |
| query | SnapshotQuery | 截帧参数 |
| opts | { Bucket?: string; Region?: string; expires?: number } | 可选覆盖桶/地域与有效期 |
返回:Promise<string>(可直接用于 <img src="...">)
示例:
const url = await uploader.snapshotUrl('video.mp4', { time: 1, format: 'jpg' })snapshot(key, query, opts?)
- 说明:获取媒体截帧图片内容(二进制)
参数:
| 名称 | 类型 | 说明 |
| --------- | ------------------------------------------------------ | ---------------- |
| key | string | 媒体文件对象 Key |
| query | SnapshotQuery | 截帧参数 |
| opts | { Bucket?: string; Region?: string; dataType?: 'blob' | 'arraybuffer' } |
返回:Promise<Blob | ArrayBuffer>
示例:
const blob = await uploader.snapshot('video.mp4', { time: 1, width: 320, height: 180 })
const imgUrl = URL.createObjectURL(blob as Blob)mediaInfo(key, opts?)
- 说明:获取媒体文件的信息(视频元数据),由 COS CI 返回
参数:
| 名称 | 类型 | 说明 |
| -------- | ---------------------------------------- | ------------------------------- |
| key | string | 媒体文件对象 Key |
| opts | { Bucket?: string; Region?: string } | 覆盖桶/地域(默认使用后端返回) |
返回:Promise<any>(COS 返回的数据结构,通常包含媒体格式、流信息等)
示例:
const info = await uploader.mediaInfo('video.mp4')
console.log(info)设计与行为说明
- 临时密钥:
- 到期前 60 秒自动刷新
- 接口请求失败时,内部自动执行指数退避重试(最多 3 次,间隔 1s/2s/4s...),防止网络抖动导致的上传失败
- 使用前会双重校验是否过期并重建实例
- 前缀覆盖:仅在
prefixOverride非空且去掉空白后仍有内容时生效,否则回退后端前缀 - 优先级:上传时
opts覆盖 > 实例配置 > 后端返回默认值 - 失败重试:线性退避
500ms × attempts,最多retryTimes次 - 并发队列:限制同时运行的任务数,任务完成后自动触发下一项
- 进度回调:同时提供
fileId与key,避免 UI 匹配不一致 - Base64 上传:若传入 Base64 字符串,会自动解析 MIME 类型并转换为 Blob,文件名为自动生成的随机 ID
常见问题
- CORS:需在 COS 控制台正确配置跨域,
AllowHeader: *,ExposeHeaders包含ETag、Content-Length等 - SDK 环境:请在浏览器环境使用
cos-js-sdk-v5,Node 环境请改用cos-nodejs-sdk-v5 - 要使自定义CDN域名访问时也能自动触发下载,需要在URL后拼接参数 response-content-disposition=attachment。具体方法如下: 在获取的URL后补充参数: url + (url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment' 如果需要重命名下载文件,可拼接: url + (url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment;filename=自定义文件名'
