Coze Studio uploader-adapter 包解析:用适配层统一 tt-uploader 上传 SDK 的接入方式
【免费下载链接】coze-studioAn AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.项目地址: https://gitcode.com/GitHub_Trending/co/coze-studio
@coze-studio/uploader-adapter是 Coze Studio 前端 monorepo 中的上传适配包,它的职责是把字节系上传 SDKtt-uploader封装成一个面向业务侧的统一入口getUploader,并在其上重新导出标准配置与事件类型。本文结合该包的 README、源码与单元测试,完整讲解它的安装方式、核心 API、配置语义与事件模型,以及测试用例如何验证 region 选择与 imageHost 回退等关键行为。
一、包的定位:一个"薄适配层"
从 package.json 可以看到这个包的全部运行时依赖只有两个:
tt-uploader@1.5.0:真正的上传 SDK(火山/字节对象存储上传);@coze-arch/uploader-interface(workspace:*):monorepo 内部的纯类型包,定义Config、STSToken、EventPayloadMaps等接口。
也就是说,adapter 本身不实现任何上传逻辑,而是做三件事:
- 按部署环境(国内/海外)决定 region,构造
tt-uploader实例; - 用统一的
FileOption入参包装底层addImageFile调用; - 重新导出
Config、EventPayloadMaps两个类型,让业务方只依赖 adapter,而不直接耦合底层 SDK 的类型定义。
包的入口文件是 src/index.ts,与main: "src/index.ts"的声明一致,即以 TypeScript 源码形式被消费(配合 Rush monorepo 的源码直用模式,build脚本为exit 0占位)。
二、安装与引入方式
按 README 的说明,在 monorepo 内的消费方包中按如下方式声明依赖:
{ "dependencies": { "@coze-studio/uploader-adapter": "workspace:*" } }然后在仓库根目录执行:
rush update导入用法(README 中的模板 + 源码实际导出):
import { getUploader } from '@coze-studio/uploader-adapter'; // adapter 实际导出的内容: // - getUploader(config, isOversea?): CozeUploader // - 类型:FileOption、CozeUploader // - 透传类型:Config、EventPayloadMaps(来自 @coze-arch/uploader-interface)源码中的完整导出清单见 src/index.ts 末尾的export { type Config, type EventPayloadMaps } from '@coze-arch/uploader-interface',与 README "API Reference / Exports" 一节列出的type Config, type EventPayloadMaps一致。
三、核心 API:getUploader工厂函数
getUploader(config: Config, isOversea?: boolean)是整个包的唯一运行时导出,其实现要点如下(源码 src/index.ts#L33-L65):
3.1 region 的自动选择
region: isOversea ? 'ap-singapore-1' : 'cn-north-1',第二参数isOversea决定使用新加坡还是北京 region。单元测试(tests/index.test.ts#L66-L84)分别验证了两种调用:默认调用得到region: 'cn-north-1',传入true得到region: 'ap-singapore-1'。
值得注意的一个细节:src/下还有一个 utils.ts,定义了更大的 region 映射表:
export const REGION_MAP = { 'cn-north-1': 'cn-north-1', 'ap-singapore-1': 'ap-singapore-1', // Volcengine has no va environment 'us-east-1': 'ap-singapore-1', };即us-east-1会被归一到新加坡。从源码结构看,该映射表目前未被index.ts引用(index.ts内采用三元表达式硬编码),属于为更细粒度 region 选择预留的工具函数。
3.2 imageHost 的解析与 schema 兼容
const imageHost = ( config.imageHost || config.imageFallbackHost || '' ).replace(/^https:\/\//, config.schema ? `${config.schema}://` : '');这段逻辑有三层语义,且每一层都被单元测试覆盖:
| 场景 | 行为 | 测试用例 |
|---|---|---|
imageHost = 'https://img.example.com' | 剥掉https://前缀,得到img.example.com | "should strip https:// from imageHost" |
缺少imageHost,提供imageFallbackHost | 回退到fallback.example.com | "should fallback to imageFallbackHost..." |
| 两者都缺失 | 使用空字符串'' | "should use empty string if no imageHost or fallback" |
剥掉协议前缀后,如果配置了config.schema(见 uploader-interface 的 Config.schema 注释:schema 需根据当前用户部署环境动态获取,仅支持https与http两个值),则再拼回对应的${schema}://前缀;否则保持无协议形式。这样做的目的是让最终 URL 的协议跟随部署环境(比如本地 HTTP 调试)而不是被写死为 HTTPS。
3.3 透传给 tt-uploader 的完整配置
工厂函数最终执行new Uploader({...}),透传的字段为:
{ schema: config.schema, region, // 由 isOversea 推导 imageHost, // 上面解析后的 host appId: config.appId, userId: config.userId, useFileExtension: config.useFileExtension, uploadTimeout: config.uploadTimeout, imageConfig: config.imageConfig, }测试用例 "should create uploader with correct config (domestic)"(index.test.ts#L66-L77)断言了这组入参,其中未提供的useFileExtension、uploadTimeout、imageConfig均为undefined。
四、addFile的统一封装
adapter 在构造出的Uploader实例上覆写了addFile(src/index.ts#L54-L63):
uploader.addFile = function (options: FileOption) { const imageOptions: ImageXFileOption = { file: options.file, stsToken: options.stsToken, }; return originalAddImageFile(imageOptions); };设计意图:业务侧只需传file(Blob)和stsToken两个核心字段,adapter 负责将其转换为底层 SDK 的ImageXFileOption并调用addImageFile。测试用例 "addFile should call addImageFile with correct params" 验证了入参原样透传、返回值(文件 key,如'mock-key')原样返回。
adapter 自定义的FileOption比透传字段更宽(src/index.ts#L24-L31),保留了type、callbackArgs、testHost、objectSync等可选字段,与 uploader-interface 中的 FileOption(含type?: 'video' | 'image' | 'object'、serviceType?: 'vod' | 'imagex'等)在命名上保持一致,便于未来扩展视频/对象直传。
CozeUploader类型则声明了 adapter 实例的完整能力面:
type UploadEventName = 'complete' | 'error' | 'progress' | 'stream-progress'; export type CozeUploader = Uploader & { addFile: (options: FileOption) => string; removeAllListeners: (eventName: UploadEventName) => void; };即继承tt-uploader的Uploader全部方法(start、pause、cancel、removeFile、refreshSTSToken、on/once/removeListener等,可参考 uploader-interface 的 BytedUploader 接口 了解完整方法签名约定),并叠加适配层覆写的addFile。
五、配置与事件类型:Config与EventPayloadMaps
adapter 从 @coze-arch/uploader-interface 透传的两个类型是整个上传体系的"契约",业务方按它组织配置与监听事件。
5.1Config:实例级配置
关键字段(完整定义见 index.ts#L59-L113):
| 字段 | 类型 | 说明 |
|---|---|---|
userId/appId | string/number | 必填,用户与空间标识 |
stsToken | STSToken? | 实例级 STS 凭证;也可在addFile时按文件传入 |
region | 枚举 | cn-north-1、ap-singapore-1、us-east-1、gcp等 |
imageHost/imageFallbackHost | string? | 图片 host 与回退 host(adapter 实际消费这两个字段) |
videoHost/videoFallbackHost | string? | 视频 host(本 adapter 未透传,供接口层其他实现使用) |
schema | string? | 协议 schema,https/http,需按部署环境动态获取 |
useFileExtension/uploadTimeout | boolean?/number? | 是否使用文件后缀 / 上传超时(adapter 透传项) |
imageConfig | ImageConfig? | { serviceId, processAction? },图片处理动作链(如CaptionUpload、Encryption) |
uploadSliceCount/getSliceFunc/uploadHttpMethod | — | 分片上传相关调优 |
skipDownload/skipMeta/skipCommit/clientEncrypt/enableDiskBreakpoint | boolean? | 跳过下载(视频)、跳过元信息(图片)、跳过 commit、客户端加密、断点续传等开关 |
STSToken结构为AccessKeyId、SecretAccessKey、SessionToken、ExpiredTime、CurrentTime五元组(index.ts#L17-L23),processAction的Action.name支持GetMeta、StartWorkflow、Snapshot、Encryption、AddOptionInfo、CaptionUpload(index.ts#L32-L41)。
5.2EventPayloadMaps:事件载荷映射
export interface EventPayloadMaps { complete: CompleteEventInfo; // 含 uploadResult: UploadResult progress: ProgressEventInfo; 'stream-progress': StreamProgressEventInfo; error: ErrorEventInfo; }四类事件的公共载荷BaseEventInfo携带startTime/endTime/stageStartTime/stageEndTime/duration时间戳、fileSize、key、oid、percent、stage、status(1 运行 / 2 取消中 / 3 暂停)、extra.message与extra.errorCode等(index.ts#L184-L222)。complete事件的uploadResult结构因文件类型而异:图片返回ImageUri、ImageWidth/ImageHeight、ImageMd5、FileName;视频返回Vid、VideoMeta、PosterUri;文件返回ObjectMeta(UploadResult 定义)。
对业务侧来说,监听上传完成的最小可用写法是:
const uploader = getUploader(config, isOversea); uploader.on('complete', (info) => { // info.uploadResult.ImageUri / info.uploadResult.Vid ... console.log(info.key, info.uploadResult); }); uploader.on('progress', (info) => { console.log(`上传进度 ${info.percent}%`); }); uploader.on('error', (info) => { console.error(info.extra.errorCode, info.extra.message); }); uploader.addFile({ file, stsToken }); uploader.start();六、测试与工程化
- 单元测试位于tests/index.test.ts:通过
vi.mock('tt-uploader')替换底层 SDK,覆盖 region 选择(国内/海外)、imageHost 前缀剥离与回退、空值兜底、addFile透传共 6 个用例,是验证适配层行为契约的唯一依据; - 脚本(package.json):
rushx test等价于vitest --run --passWithNoTests,另有test:cov(v8 覆盖率)与lint(ESLint); - 工具链遵循 monorepo 规范:
@coze-arch/eslint-config、@coze-arch/ts-config、@coze-arch/vitest-config均为workspace:*内部包,测试使用@vitest/coverage-v8与sucrase转换,Vitest 版本锁定在~3.0.5。
七、小结
@coze-studio/uploader-adapter展示了 Coze Studio 前端处理"底层云上传 SDK"的典型分层方式:
- 接口层(
@coze-arch/uploader-interface)沉淀Config、事件载荷等纯类型契约; - SDK 层(
tt-uploader@1.5.0)负责真正的分片上传、STS 鉴权与断点续传; - 适配层(本包)以
getUploader工厂收敛环境差异(region、schema、imageHost 回退),并以统一的addFile(FileOption)面向业务暴露 API。
对需要在 Coze Studio 内接入上传能力的开发者,核心动作就是:实现方提供Config(含userId/appId/imageHost)与每次上传的STSToken,通过getUploader(config, isOversea)拿到实例后addFile+start,再按EventPayloadMaps监听complete/progress/error事件即可。
【免费下载链接】coze-studioAn AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.项目地址: https://gitcode.com/GitHub_Trending/co/coze-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考