@seaart/edge-media-upload
v0.1.2
Published
SeaArt browser media upload client for the edge upload protocol
Readme
@seaart/edge-media-upload
SeaArt 浏览器端统一媒体上传核心包,支持图片、GIF、视频和音频。
上传流程:
- 获取
/api/upload/edge/pre-sign预签名。 - 使用
vod-js-sdk-v6上传主媒体;视频封面附件使用预签名 URL 直传。 - 调用
/api/upload/edge/complete转换为站内 CDN 地址。
包本身不依赖 Vue、Nuxt、Element 或具体请求库。登录态、请求 Header、UI 提示和埋点由业务项目通过请求配置与 hooks 注入。
使用
import { createMediaUploadClient } from '@seaart/edge-media-upload';
const client = createMediaUploadClient({
baseURL: 'https://api.example.com',
getHeaders: () => ({ Authorization: getAuthorization() }),
});
const result = await client.upload(file, { category: 2 });需要进度或取消能力时:
const uploader = client.createUploader({
file,
category: 8,
onProgress: (_event, progress) => updateProgress(progress),
});
const result = await uploader.beforeUpload();
uploader.cancel();客户端参数
createMediaUploadClient(config) 的配置如下:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| ---------------- | ----------------------------------------------------------------- | ---- | ---------------------- | ---------------------------------------------------- |
| baseURL | string | 否 | '' | API 基础地址。空字符串表示使用当前站点的 /api 代理 |
| getHeaders | () => Record<string, string> \| Promise<Record<string, string>> | 否 | - | 每次业务请求前获取登录态、游客标识、语言等 Header |
| request | (options: UploadRequestOptions) => Promise<unknown> | 否 | 内置 fetch | 自定义业务请求方法,适配 Web/H5 的统一请求封装 |
| hooks | UploadHooks | 否 | - | 上传结果、通用错误和 SDK 错误回调 |
| bucket | string | 否 | 'image' | 预签名参数中的存储 bucket |
| preprocessFile | (file) => file \| Promise<file> | 否 | - | 文件上传前预处理,例如图片转 WebP |
| loadVodSdk | () => Promise<VodClientConstructor> | 否 | 懒加载 vod-js-sdk-v6 | 自定义 SDK 加载器,主要用于测试或特殊运行环境 |
baseURL、getHeaders、request 是请求相关配置。未传 request 时,公共包使用内置 fetch,并固定设置 credentials: 'include'。
上传参数
client.upload(file, options) 和 client.createUploader(options) 使用以下参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| ---------------------------------------- | --------------------------------------- | ---- | --------------------------- | -------------------------------------------------------------------------------------------- |
| file | File \| Blob | 是 | - | 主媒体文件。client.upload() 通过第一个参数传入,实例模式可在创建或 beforeUpload() 时传入 |
| category | string \| number | 是 | - | 资源业务分类。上传前会校验,并保留在上传生命周期上下文中 |
| name | string | 否 | 文件原名 | 高阶上传入口中的文件名别名 |
| mediaName | string | 否 | 文件原名 | 传给 VOD SDK 的媒体名称,并作为缺失文件名时的兜底 |
| templateId / template_id | string \| number | 否 | - | 应用模板 ID,保留用于兼容现有调用方 |
| maxSize | number | 否 | 图片/视频 1 GB,音频 100 MB | 文件大小上限,单位为字节 |
| chunkSize | number | 否 | 预签名返回值或 SDK 默认值 | VOD SDK 主媒体分片大小,单位为字节,必须为正整数 |
| preprocess | boolean | 否 | true | 是否执行客户端 preprocessFile,仅作用于 client.upload() |
| onProgress | (event, progress) => void | 否 | - | 主媒体上传进度回调,progress 范围为 0-100 |
| trackResult | boolean | 否 | true | 设为 false 时不触发 hooks.onResult,用于避免兼容层重复上报 |
| uploadTrack | unknown | 否 | - | 业务埋点上下文,保留在 Hook 的 event.params 中,不传给 SDK |
| other.templateId / other.template_id | string \| number | 否 | - | client.upload() 对模板 ID 的兼容取值 |
| getSignature | (params) => string \| Promise<string> | 否 | - | 高级覆盖项,直接提供 VOD 签名并跳过默认 pre-sign 请求,参见下方注意事项 |
| 其他字段 | unknown | 否 | - | 未被公共包消费的字段会透传给 VOD SDK 的 upload() 参数 |
当前不支持调用方传入视频封面。上传视频时,公共包会尝试截取视频首帧并生成临时 WebP 封面,再通过 pre-sign 返回的 attachments[].pre_signs[] 单独 PUT 上传。
chunkSize 的取值优先级为:调用方参数 > pre-sign.data.chunk_size > VOD SDK 默认值。传入 chunkSize 后只覆盖主媒体的 SDK 分片大小,不改变自动生成封面附件的服务端分片规则。
预签名参数
公共包根据文件自动生成:
{
name: file.name,
size: file.size,
bucket: 'image',
hash: md5(file.name),
attachments: generatedCoverFiles.map(/* 同样的 name/size/bucket/hash */),
}其中 attachments 仅在存在视频封面时携带。
使用
getSignature会跳过默认pre-sign,公共包因而无法获得uploadId和封面attachments。仅应在自定义后端链路不依赖这些字段时使用,普通业务上传不要配置。
实例方法与状态
client.createUploader(options) 返回 MediaUploader:
| 方法 | 说明 |
| ------------------------------- | ---------------------------------------------------- |
| beforeUpload(file?, options?) | 开始上传,保留旧版调用名称 |
| upload(file?, options?) | beforeUpload() 的别名 |
| cancel() | 取消 SDK、附件和业务接口请求,并使旧任务异步回调失效 |
| applyOptions(options) | 更新实例参数 |
| resetStatus() | 将进度和结果重置为初始状态 |
可读取的主要状态:
| 字段 | 说明 |
| ----------------- | ------------------------------------------------------- |
| uploading | 当前是否正在上传 |
| uploadingStatus | init、pending、complete、error 或 cancelled |
| progress | 主媒体上传进度,范围为 0-100 |
| result | 当前上传结果 |
| uploadId | pre-sign 返回的任务 ID |
| preSigns | 主媒体预签名列表 |
| chunkSize | 当前任务实际使用的分片大小;未指定且后端未返回时为 0 |
| exceptChunkNum | 后端返回的期望分片并发数,对应 SDK chunkParallelLimit |
返回值
上传成功返回 UploadResult:
| 字段 | 类型 | 说明 |
| --------------------------- | --------------------- | -------------------------------------------------- |
| url | string | complete 返回的最终资源地址 |
| info | VodUploadResult | SDK 原始结果,媒体 URL 已替换为最终资源地址 |
| fileId | string | VOD SDK 返回的文件 ID;SDK 未返回时为空字符串 |
| image / video / audio | object \| undefined | 对应媒体类型的 SDK 结果 |
| lowPath | string | complete.low_path,低清 WebP 地址 |
| coverUrl | string | complete.cover_url,高清 WebP/视频封面地址 |
| uploadId | string | 预签名上传任务 ID |
| preSigns | PreSignItem[] | 主媒体预签名列表 |
| exceptChunkNum | number | 实际使用的 SDK 分片并发参数 |
Hooks
const client = createMediaUploadClient({
hooks: {
onResult(event) {},
onError(error, context) {},
onSdkError(error, context) {},
},
});| Hook | 触发时机 |
| ------------ | --------------------------------------------------------------- |
| onResult | 上传最终成功或失败时触发;event.status 为 success 或 fail |
| onError | 当前有效任务发生错误时触发 |
| onSdkError | VOD SDK 已开始但尚未完成时发生错误 |
Hooks 中抛出的异常不会改变上传结果。公共包自身的校验和协议异常使用 EdgeMediaUploadError,包含可选的 code、requestId 和 stage;自定义 request 或 VOD SDK 抛出的原始异常会原样向上传调用方抛出。
请求配置
请求相关配置只有三个:
baseURL:可选,默认空字符串,使用当前站点的/api代理。getHeaders:可选,支持同步或异步返回登录态、游客标识、语言等 Header,用于pre-sign和complete。request:可选,自定义请求实现;未传时使用内置fetch,并固定设置credentials: 'include'。
自定义 request 示例:
const client = createMediaUploadClient({
baseURL: '',
getHeaders: () => ({ 'X-Device-Id': getDeviceId() }),
request: ({ url, method, data, headers, signal }) =>
request({
url,
method,
data,
headers,
signal,
customConfig: { needRemovePending: false },
}),
});request 可以返回完整业务响应 { data, status },也可以直接返回 data。完整响应的成功状态码必须为 10000。
默认上传流程只调用预签名和完成确认两个接口,不再调用 fast-confirm。自定义 request 必须透传 signal,并关闭相同上传请求的去重取消。
request 接收的参数:
| 参数 | 类型 | 说明 |
| --------- | ------------------------ | ------------------------------------------------------ |
| url | string | 已拼接 baseURL 的最终接口地址 |
| method | 'POST' | 当前三个业务接口均为 POST |
| data | unknown | 接口请求体 |
| headers | Record<string, string> | pre-sign 和 complete 为默认 Content-Type 与 getHeaders() 返回值的合并结果;fast-confirm 仅发送 Content-Type |
| signal | AbortSignal | 当前上传任务的取消信号,必须透传到底层请求 |
接口响应
三个业务接口均使用统一响应外层:
{
data: T | null,
status: {
code: number | string,
msg?: string,
request_id?: string,
},
}status.code 为 10000 时视为成功,否则抛出 EdgeMediaUploadError。
pre-sign
{
data: {
id: 'edge_xxx',
pre_signs: [{ url: '<vod-signature>', size: 33522 }],
status: 1,
chunk_size: 33522,
except_chunk_num: 1,
attachments: [], // 仅视频封面存在时返回
},
status: { code: 10000, msg: 'success', request_id: 'xxx' },
}| 字段 | 说明 |
| ------------------ | ------------------------------------------------------ |
| id | Edge 上传任务 ID,后续传给 complete |
| pre_signs | 主媒体签名列表;当前使用第一项 url 作为 VOD SDK 签名 |
| chunk_size | SDK 分片大小,对应 chunkSize |
| except_chunk_num | SDK 分片并发数,对应 chunkParallelLimit |
| attachments | 视频封面附件的路径及 PUT 预签名列表 |
complete
{
data: {
path: 'upload/static/20260723/example.webp',
low_path: 'https://image.seaartcdn.com/upload/static/20260723/example.webp?eo-img.resize=w/474&eo-img.format=webp',
url: 'https://image.seaartcdn.com/upload/static/20260723/example.webp',
cover_url: 'https://image.seaartcdn.com/upload/static/20260723/example.webp',
},
status: { code: 10000, msg: 'success', request_id: 'xxx' },
}| 字段 | 说明 |
| ----------- | ----------------------------------------------------- |
| path | CDN 内部相对路径 |
| url | 最终资源地址,也是 UploadResult.url 的来源 |
| low_path | 低清 WebP 地址,传给 fast-confirm.low_webp |
| cover_url | 高清 WebP/视频封面地址,传给 fast-confirm.high_webp |
fast-confirm
{
data: {
file_id: '',
url: 'https://image.seaartcdn.com/upload/static/20260723/example.webp',
video_info: null,
},
status: { code: 10000, msg: 'success', request_id: 'xxx' },
}| 字段 | 说明 |
| ------------ | --------------------------------------------------------------------- |
| file_id | 风控确认后的文件 ID;为空时 UploadResult.fileId 回退到 SDK fileId |
| url | 鉴定通过后原样返回的资源地址 |
| video_info | 视频附加信息;非视频或后端未生成时可能为 null |
浏览器与 SSR
包可以在 SSR 构建阶段安全导入,但上传只能在浏览器环境执行。腾讯云 VOD SDK 会在上传开始后懒加载。
