diff --git a/docs/adr/【ADR】0003-3D资源客户端媒体投影与格式真实性-2026-09-21.md b/docs/adr/【ADR】0003-3D资源客户端媒体投影与格式真实性-2026-09-21.md index 7bb1092f4..00b9df2bd 100644 --- a/docs/adr/【ADR】0003-3D资源客户端媒体投影与格式真实性-2026-09-21.md +++ b/docs/adr/【ADR】0003-3D资源客户端媒体投影与格式真实性-2026-09-21.md @@ -10,4 +10,6 @@ 后果:下载 3D 资源时按真实响应头的 MIME 命名、对象键扩展名兜底、最后回落 `glb`,导出目录用 `3d_models/` 与图片、其它媒体分开;类型角标、缩略图和后台渲染器只要读 `imageSrc` 就能拿到预览图,不必各自识别媒体语义;查看器包单模型体积上限 64 MiB,超限与 `webgl-unavailable` 都作为失败原因展示给用户,而不是静默失败。 +多文件模型不在支持范围内:站内 3D 产物是单文件的(`.glb` 自带几何与贴图,`.fbx` 按媒体内嵌处理),不假设会出现「模型文件 + 同目录 buffer / 贴图」这种产物,最多是「模型 + 一个 bin」。因此 `packages/model3d-viewer` 里把模型地址的签名 query 顺带补到同目录兄弟资源地址上的那段逻辑(`resolveModel3dViewerResourceUrl`)只是兜底,不代表查看器支持多文件模型:签名按单个文件签发时,贴到另一个文件上会被云端以签名不匹配拒绝。将来真要支持多文件模型,正确做法是让宿主为每个兄弟文件分别换取各自的临时地址,而不是继续扩展这段拼接。 + 未进入项:AGC 项目画布自带的两份格式判断(`isResourceModelFbx` 把 `octet-stream` 当 FBX、资源卡预览用扩展名正则选解析器)本期不动,后续统一收敛到 `packages/model3d-viewer`;素材库行、后台 renderer、精选 read model 与公开 grant 的 3D 展示同样未进入。 diff --git a/packages/model3d-viewer/src/loader.ts b/packages/model3d-viewer/src/loader.ts index 6c6caac40..7b122b6db 100644 --- a/packages/model3d-viewer/src/loader.ts +++ b/packages/model3d-viewer/src/loader.ts @@ -309,11 +309,16 @@ export function resolveModel3dViewerSourceQuery( /** * 给模型目录下的兄弟资源地址补回模型地址的鉴权 query。 * - * `GLTFLoader` / `FBXLoader` 用 `path + uri` 拼多文件模型的兄弟 buffer 与贴图地址, - * 地址落在模型目录里,但签名 token 在这一步丢掉了(目录本身不带 query),私有对象 - * 于是 401/403。这里只补模型目录下的地址:既不把 token 外发到第三方 CDN,也不把 - * 「为某个对象签出的 token」贴到同源的另一个对象上(OSS 会以 SignatureDoesNotMatch - * 拒绝),资源地址自己带的 query 也保留。 + * 前提:站内的 3D 产物是单文件的——`.glb` 自带几何与贴图,`.fbx` 也按媒体内嵌处理; + * 「同目录另有 buffer / 贴图」的多文件模型不会出现,即使出现,兄弟文件也只会有 + * 「模型 + 一个 bin」这一个。因此下面这段拼接只是最后一层兜底,不是对多文件模型的 + * 支持:签名是按单个文件签的,把模型地址的 token 贴到另一个文件上,云端多半以 + * SignatureDoesNotMatch 拒绝,读不到就是读不到,不指望它真能救回来。真要支持多文件 + * 模型,得改成让宿主给每个兄弟文件分别换取各自的临时地址,而不是继续扩这段拼接。 + * + * `GLTFLoader` / `FBXLoader` 用 `path + uri` 拼兄弟资源地址,签名 token 在这一步就丢了 + * (目录本身不带 query),私有对象于是 401/403。这里只补模型目录下的地址:既不把 token + * 外发到第三方 CDN,资源地址自己带的 query 也保留。 */ export function resolveModel3dViewerResourceUrl(input: { url: string;