把素材传到你的对象存储(OSS、COS、TOS、S3),换回一条公网直链。
把素材库里的文件传到你自己的桶里,换回一条公网直链;也能列出桶里的对象、给已有对象签直链、把对象拉回素材库。 随应用内置,装好就在插件页里。
一个连接对一个桶,服务商是连接的一项配置:
| 服务商 | 接入点留空时 | 签名 | 预签名最长 |
|---|---|---|---|
| 阿里云 OSS | oss-<地域>.aliyuncs.com | 原生 V4(OSS4-HMAC-SHA256) | 7 天 |
| 腾讯云 COS | cos.<地域>.myqcloud.com | 原生 q-sign-algorithm=sha1 | 不限 |
| 火山引擎 TOS | tos-<地域>.volces.com | TOS4-HMAC-SHA256 | 7 天 |
| Amazon S3 | s3.<地域>.amazonaws.com | SigV4 | 7 天 |
| S3 兼容服务 | 必填(如 http://localhost:9000) | SigV4,路径式寻址 | 7 天 |
腾讯云的桶名要填带 APPID 的全名,如 examplebucket-1250000000。S3 兼容服务(MinIO、Cloudflare R2……)
走路径式寻址(<接入点>/<桶>/<对象>)—— 自建服务多半没给每个桶配泛域名;接入点可以写 http://。
Cloudflare R2 的地域填 auto。
Mosael 是本地优先的:素材库里的文件在你自己的盘上,没有公网地址。而有些供应商只收链接 —— 火山方舟 Seedance 的参考视频就是一例。官方文档写得很清楚:
请确保 URL 是公网可公开访问的链接(建议存放在 TOS 对象存储服务中,并配置为公共读)
而且它明确不收 Base64:参考图可以走 data URL,参考视频不行。
storage_upload 就是那座桥:把素材传上去,交回一条限时直链。签名在查询串里,所以
桶不必设成公共读 —— 那条地址谁拿到谁能下,但过期就失效。它在清单里声明了 public_url,
生成时遇到只收链接的那一格而你给的是本地素材,宿主会自动调它(配了几个桶就在「设置 → 能力提供方 → 素材外链」里
选默认用哪一个),同一份素材在链接过期之前复用,不重复上传。
| 工具 | 名字 | 干什么 |
|---|---|---|
storage_upload | 上传到对象存储 | 传一份素材上去,交回限时直链 + 公共读地址。流式:大文件分片上传、边传边报进度,取消时停在片与片之间并清掉已传的分片 |
storage_presign | 签一条限时直链 | 给桶里已有的对象签一条限时直链 |
storage_fetch | 从对象存储取回 | 把桶里的对象拉回素材库(交地址,由宿主搬字节 —— 进度、取消、重试都归它)。对象路径声明成 format: "external_id":按桶里的地址取回是导入,不是内容变换,工作流和对话里用,不上画板 |
storage_list | 列出桶里的对象 | 列出某个前缀下的对象,一页最多 1000 条,还有下一页时交回 next_cursor |
默认对象键是 mosael/<内容指纹>/<原文件名>:两份都叫 image.png 的素材不会互相覆盖,
同样的内容重传落在同一个键上。
上传超过 64MB 走分片(Initiate → UploadPart × N → Complete,四家同一套),每片单独重试 (限流、服务端临时错误、网络断开),失败或取消就 Abort —— 分片留在桶里是要收存储费的,而且在控制台里看不见。
失败按原因说人话:桶在别的地域时点名该填哪个地域、密钥不对、没权限、时钟偏差、桶不存在……并带上原始错误码。
插件进程是按 stdio 协议跑的短命脚本。装一整个 SDK 只为签几种请求,代价是安装体积、版本冲突,
以及一条我们控制不了的供应链。签名本身是一页纸的算法,纯 hmac + hashlib:
tools/sigv4.py —— SigV4 系三家(S3 / TOS / OSS)同源但不同字:算法名、日期头、scope 结尾、
密钥派生链的第一步、预签名的参数名各不相同;阿里云 V4 的结构也不同(只签默认那几类头、
AdditionalHeaders 那一行、没有值的查询参数只写名字)。tools/qsign.py —— 腾讯云 COS 的原生签名,和 SigV4 不是一系。每一种签名(包括分片上传的四种请求)都拿官方 SDK 在同样输入下算出的向量对过
(backend/tests/test_*_signature_matches_the_sdk.py、test_object_storage_multipart_matches_the_sdk.py)。
此前是四个插件包(阿里云 OSS / 腾讯云 COS / 火山引擎 TOS / Amazon S3),上传、列目录这些主体在包之间
逐字节拷贝、靠一条测试钉着不漂。而它们之间的差异只有 tools/providers.py 那一张表 ——
签名方言、默认接入点、预签名上限、寻址方式。现在主体(tools/storage.py)一行都不认识「阿里云」,
加一家就是往表里加一行。
升级时老的四个插件由迁移 merge-object-storage-plugins 原地合进来:连接 id 不变,配置、密钥(不解密,
只改键名)、授权、工具开关、「素材外链」的默认、直链缓存、工作流和画板上的节点都跟着搬,老包的文件夹删掉。
建一个只对这一个桶有读写权限的子用户 / RAM 用户,别用主账号密钥。插件读得到的只有这个连接的 配置和那一对密钥 —— 它没有数据库、没有 API 令牌、没有媒体目录(那是隔离边界的一部分)。
storage_upload把一份素材传上去,交回一条限时直链(签名在查询串里,桶不必设成公共读)。这就是「本地文件怎么变成公网链接」的答案 —— 直接粘进生成节点的参考视频那一格。大文件分片上传,边传边报进度。
storage_presign给桶里已有的对象签一条限时直链。
storage_fetch把桶里的一个对象拉回素材库。交回的是地址,由宿主搬字节 —— 进度、取消、重试都归它。
storage_list列出桶里某个前缀下的对象(路径、大小、修改时间)。一页最多 1000 条,还有下一页时交回 next_cursor。
权限是逐项给的:装之前,应用会把它声明的权限摊开给你看。本地脚本以你当前用户的权限运行,只装信得过的来源。