- 前端
- UI组件
- 后端
【免费下载链接】uppy
The next open source file uploader for web browsers :dog:
导读
@uppy/transloadit是 Uppy 生态中连接「开源浏览器上传体验」与「Transloadit 托管后端处理」的官方插件:Uppy 负责收集文件与展示进度,Transloadit 负责接收文件并执行视频转码、图片缩放、压缩/解压等处理工作流(Assembly)。读完本文,你将掌握该插件的安装方式、assemblyOptions服务端签名接入模式、全部可配置项与事件体系,并通过源码理解 Assembly 创建、tus 直传、SSE 状态推送的完整调用链,可直接在自己的 JavaScript / React / Next.js / Vue / Angular 项目中落地。
插件定位:Uppy 与 Transloadit 各司其职
从 插件 README 的定位描述可以明确本插件的分工:
- Uppy 负责开源的上传端体验:文件选择、拖拽、进度展示、取消重试;
- Transloadit 是托管后端:接收上传的文件并运行预定义的处理流程;
- 本插件负责把两者连接起来:创建 Assembly(处理任务)、把文件用 tus 协议直传到 Transloadit、监听并暴露处理进度与结果。
因此 Transloadit 并不是 Uppy 的唯一上传目的地——Uppy 同样支持 S3、自有服务器等目的地,本插件只是「其中一条路」。这个定位决定了本插件的核心抽象:Assembly(一次文件处理任务的容器),它由服务端通过 Transloadit API 创建,携带处理模板(steps)与认证信息。
从 package.json 可以看到其运行时依赖只有三样:@transloadit/types(类型定义)、@uppy/tus(上传传输层)、component-emitter(事件机制),而@uppy/core是其 peer 依赖,说明插件深度集成 Uppy 的核心生命周期。
安装
$ npm install @uppy/transloadit依赖关系上它还会自动引入@uppy/tus(见 package.json),因此不需要手动安装 tus 插件。
除 npm 外,还可以通过 Transloadit 的 Smart CDN 直接使用预构建 bundle,此时Uppy会挂载到全局window.Uppy对象上,按主 Uppy 文档的安装说明引入即可。
快速上手:服务端签名的标准姿势
README 给出的最小可用示例是:
import Uppy from '@uppy/core' import Transloadit from '@uppy/transloadit' const uppy = new Uppy().use(Transloadit, { async assemblyOptions() { const response = await fetch('/api/transloadit-params', { method: 'POST' }) if (!response.ok) { throw new Error(`Could not prepare the upload (${response.status})`) } return response.json() }, })这段代码有两个关键点需要展开:
1.assemblyOptions既可以是对象,也可以是异步函数。从 插件源码的类型定义 可以看到它被定义为AssemblyOptions | (() => Promise<AssemblyOptions> | AssemblyOptions)。在#prepareUpload钩子中,插件会在每次上传开始前调用该函数取得最新参数(index.ts#L856-L860),因此可以在服务端动态签发、携带时效性的签名。每次调用返回的AssemblyOptions由三部分组成(index.ts#L35-L39):
| 字段 | 类型 | 说明 |
|---|---|---|
params | 对象或 JSON 字符串 | Assembly 指令,至少包含auth.key;内容会被JSON.stringify后以表单字段提交(见 Client.ts#L113-L117) |
fields | 对象或字符串数组 | 随 Assembly 一起提交的额外表单字段(如业务元数据) |
signature | 字符串 | 服务端用 Auth Secret 对params计算的签名,用于校验参数未被篡改 |
2. 认证密钥绝不允许出现在浏览器代码中。README 明确警告:params与signature必须在服务端生成,永远不要把 Transloadit Auth Secret 写入前端代码。源码中的validateParams也印证了这一点——它在本地只校验params.auth.key(index.ts#L172-L198),而params与signature的完整内容正是来自服务端接口的响应。README 推荐的官方完整示例(JavaScript、React、Next.js、Vue、Angular 五种框架的服务端签名接入指南)均可按需查阅。
完整配置项与默认值
以下配置项均来自 插件源码的默认配置,是当前仓库版本(6.0.0)的真实取值:
const defaultOptions = { service: 'https://api2.transloadit.com', // Transloadit API 服务地址 errorReporting: true, // 出错时是否上报给 Transloadit 用于改进 waitForEncoding: false, // 是否等待编码完成拿到 results waitForMetadata: false, // 是否等待元数据提取完成 alwaysRunAssembly: false, // 空文件集是否也运行 Assembly importFromUploadURLs: false, // 是否改用「导入上传 URL」模式 limit: 20, // 并发上传数 retryDelays: [7_000, 10_000, 15_000, 20_000], // tus 失败重试延迟(毫秒) clientName: null, // 附加到 Transloadit-Client 头的自定义标识 }逐项解读:
service:插件内部Client构造时直接使用该地址拼接/assemblies端点(Client.ts#L127)。只有在使用私有部署或区域端点时才需要修改。waitForEncoding/waitForMetadata:控制上传完成后是否继续等待处理阶段。从 index.ts#L825-L839 可以看到:开启waitForEncoding时会订阅result与finished事件;只开waitForMetadata时订阅metadata事件。若两者都关闭,插件在上传完成后立即关闭连接并结束(index.ts#L919-L928)。注意waitForMetadata的优先级低于waitForEncoding——后者开启时前者被忽略。limit:创建内部RateLimitedQueue的并发上限(index.ts#L278),并透传给内部 tus 插件(index.ts#L1029)。retryDelays:同样透传给 tus 插件控制失败重试节奏。errorReporting:Client.#reportError中,若为false则直接抛错不上报(Client.ts#L237-L239)。alwaysRunAssembly:从源码结构看,它用于控制是否在无文件时也创建并运行 Assembly,属于面向「先占位后补文件」场景的开关。
assemblyOptions返回的对象在进入Client.createAssembly前还会被补上expectedFiles: fileIDs.length字段(index.ts#L404-L407),并最终以num_expected_upload_files表单字段提交(Client.ts#L125),告知 Transloadit 本次 Assembly 应收多少个文件。
底层工作流:一次上传背后的调用链
结合源码可以把一次「选择文件 → 处理完成」拆成五个阶段,这也是理解插件行为的关键:
1. 预处理阶段(preprocessor):#prepareUpload被注册为 Uppy 的预处理器(index.ts#L997)。它先锁定allowNewUpload: false防止上传期间混入新文件,然后调用assemblyOptions()并校验params,再调用client.createAssembly()。
2. 创建 Assembly:Client.createAssembly用FormData提交params、signature、fields与num_expected_upload_files到POST {service}/assemblies(Client.ts#L105-L133)。创建失败时会抛出一个携带details与assembly上下文、以Transloadit: Could not create Assembly:开头的错误(index.ts#L439-L454),测试用例 index.test.js 验证了该错误消息与「失败后不残留上传进度」的行为。
3. 附加 tus 元数据:#attachAssemblyMetadata把 Assembly 返回的assembly_url、tus_url、assembly_id写入每个文件的 meta 与 tus 配置(index.ts#L339-L395),使文件直接上传到该 Assembly 专属的 tus 端点。对于远程来源文件(如 Google Drive、Dropbox),若其 Companion 由 Transloadit 托管,还会自动替换为 Assembly 返回的companion_url主机。
4. 上传阶段:默认情况下插件内部会自动注册@uppy/tus,并做两个重要配置(index.ts#L1014-L1032):
storeFingerprintForResuming: false:禁用 tus 默认断点续传指纹,因为 Transloadit 的续传需要 Golden Retriever 保存的 Assembly 状态,而不是 tus 自己的指纹;allowedMetaFields: true:把全部用户元数据随上传发给 Transloadit,供模板中以file.user_meta使用。
5. 后处理阶段(postprocessor):#afterUpload根据waitForEncoding/waitForMetadata决定是否阻塞等待,最终把 Assembly 状态写入上传结果数据transloadit字段(index.ts#L899-L964)。
状态监听双通道:SSE 推送 + 轮询兜底
Assembly 创建后,Assembly类(Assembly.ts)负责跟踪其状态,采用「SSE 为主、轮询兜底」的双通道设计:
- SSE:通过
EventSource连接websocket_url,监听message(assembly_finished、assembly_uploading_finished、assembly_upload_meta_data_extracted)、assembly_upload_finished、assembly_result_finished、assembly_execution_progress、assembly_error等事件(Assembly.ts#L87-L160)。SSE 打开成功后会停掉轮询。 - 轮询:SSE 不可用时,每 2 秒向 assembly 状态端点拉取一次完整状态(Assembly.ts#L176-L180);收到 429 时触发 2 秒限流(Assembly.ts#L205-L208)。
轮询路径还实现了状态差异对比(#diffStatus):即使某次拉取时状态已从ASSEMBLY_UPLOADING直接跳到ASSEMBLY_COMPLETED,也会按「executing → 若干 upload → metadata → 若干 result → finished」的顺序补齐事件,保证不丢事件(Assembly.ts#L247-L315)。这是测试文件 Assembly.test.js 覆盖的核心逻辑。
多个 Assembly 的完成聚合由AssemblyWatcher负责(AssemblyWatcher.ts):它监听transloadit:complete、transloadit:assembly-cancel、transloadit:assembly-error、transloadit:import-error事件,计数全部完成(或失败)后 resolve 其promise,#afterUpload正是await这个 promise 来阻塞上传流程(index.ts#L947)。
事件体系:在 UI 中订阅处理结果
插件在 Uppy 事件图上声明了一整套transloadit:前缀事件(index.ts#L111-L147):
| 事件 | 触发时机 |
|---|---|
transloadit:assembly-created | Assembly 创建成功,携带状态与文件 ID 列表 |
transloadit:assembly-error | Assembly 处理失败 |
transloadit:assembly-executing | 上传完成、进入执行阶段 |
transloadit:execution-progress | 执行进度更新(progress_combined,0~100) |
transloadit:upload | 单个文件上传完成 |
transloadit:result | 单个处理结果产出,携带stepName与result |
transloadit:complete | Assembly 全部处理完成 |
transloadit:assembly-cancelled | Assembly 被取消 |
transloadit:import-error | importFromUploadURLs模式下导入单个文件失败 |
restored/restore:plugin-data-changed | Golden Retriever 恢复上传状态时 |
执行进度(progress_combined)会被映射为每个文件的postprocess-progress事件,UI 层(Dashboard 等)因此能显示「Encoding...」进度条(index.ts#L799-L823);本地化文案(Preparing upload...、Transloadit: Could not create Assembly、Encoding...)定义在 locale.ts。
读取结果的典型模式是监听complete回调,从上传结果数据中取transloadit数组,再读取results:
uppy.on('complete', ({ transloadit, successful, failed }) => { if (failed?.length !== 0) return // transloadit[0] 是本次上传的 Assembly 最终状态 // transloadit[0].results.resize[0].ssl_url 是 resize 步骤产出的文件地址 })注意:只有开启waitForEncoding时结果才会被收集并出现在complete数据里;否则上传结束即返回,处理在后台继续。
进阶模式:导入上传 URL 与断点恢复
importFromUploadURLs: true适合「文件先传到别处(如自有 S3),再由 Transloadit 拉取处理」的架构。该模式下插件不再注册内部 tus 上传器,而是监听upload-success事件,等文件获得uploadURL后调用reserveFile预留资源、addFile把远端 URL 导入 Assembly(index.ts#L1008-L1010、Client.ts#L138-L177)。源码注释显示其配套支持 XHRUpload、AwsS3、Dropbox、GoogleDrive、Url 等来源的版本标识上报(index.ts#L310-L324)。
断点恢复依赖@uppy/golden-retriever:插件把assemblyResponse持久化,restored事件触发时通过#onRestored重建 Assembly 实例、重连状态监听并强制拉取一次最新状态以补回错过的更新(index.ts#L686-L781)。同时如前所述,tus 默认的指纹续传被显式关闭,避免续传指向过期的 Assembly。
仓库内可运行的本地 Demo
仓库自带的 examples/transloadit 是一个完整的、可运行的本地示例(仅用于测试),展示了多种集成形态:
- Form 集成:上传完成后把结果写回表单,配合
@uppy/form提交到服务端; - Dashboard 集成:内嵌面板 / 弹窗两种模式,叠加 Webcam 拍摄、ImageEditor 编辑、RemoteSources 远程来源;
- 无 UI 纯代码集成:直接
uppy.addFiles()+uppy.upload(),complete回调里从transloadit[0].results.resize[0].ssl_url取缩放结果渲染图片。
其 main.js 展示了waitForEncoding: true与静态assemblyOptions的用法(示例用公开演示 Auth Key + 图片缩放模板,仅供本地探索)。服务端 server.js 则演示接收表单提交并展示 Assembly 的 uploads 与 results。启动方式(需先在仓库根目录完成依赖安装与构建):
corepack yarn install corepack yarn build corepack yarn workspace example-transloadit start注意:Demo 用的是无签名的公开 Key,不适合生产。生产环境务必按上文「服务端签名」方式,让服务端生成
params与signature。
常见问题与安全红线
params与auth.key缺失:插件会直接抛错The params option is required.或The params.auth.key option is required.(index.ts#L172-L198),Key 可在 Transloadit 控制台凭据页获取。params是非法 JSON 字符串:插件会抛出带原始解析错误原因的错误,便于排查(index.ts#L183-L187)。- Auth Secret 泄入前端 = 账号失守:签名必须只在服务端计算;前端只持有
auth.key与动态signature。 - 上传取消:插件禁用了单文件取消能力(
individualCancellation: false,index.ts#L1046-L1053),因为一个 Assembly 内通常包含多个文件;cancel-all会调用DELETE {assembly_ssl_url}真正取消远端 Assembly(Client.ts#L182-L188)。
许可证
本插件以 MIT 许可证 发布,可自由用于商业与非商业项目。
- 前端
- UI组件
- 后端
【免费下载链接】uppy
The next open source file uploader for web browsers :dog:
相关推荐
Uppy Transloadit Storage 插件完全指南:在 Dashboard 中浏览、管理并上传到 Transloadit 存储工作区
Uppy Transloadit Storage 插件完全指南:在 Dashboard 中浏览、管理并上传到 Transloadit 存储工作区 @uppy/t
前端UI组件后端Uppy × Transloadit 集成实战:用 @uppy/transloadit 打通浏览器上传与托管转码流水线
Uppy × Transloadit 集成实战:用 @uppy/transloadit 打通浏览器上传与托管转码流水线 导读 本文基于仓库中的可运行示例 exa
前端UI组件后端Uppy GoldenRetriever 插件完全指南:从浏览器崩溃中恢复文件与续传上传的实现演进
Uppy GoldenRetriever 插件完全指南:从浏览器崩溃中恢复文件与续传上传的实现演进 GoldenRetriever 是 Uppy 生态中用于「崩
前端UI组件后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考