diff --git a/docs/technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md b/docs/technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md index 0b0c7aa9d..0710e599c 100644 --- a/docs/technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md +++ b/docs/technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md @@ -162,7 +162,7 @@ thumbnailSrc = 预览图 width/height = 预览图像素尺寸 ``` -模型格式与体积由 `AssetObject` 承担(`content_type`、`content_length`、`content_hash`),因此不新增 `model_format`、`size_bytes`、`poly_count` 等列。两个槽位的 `content_type` 都在写入前按字节识别真实产物:模型按魔数认 GLB 的 `glTF` 头、FBX 的 `Kaydara FBX Binary` 头与 glTF 的 JSON 正文,预览按魔数认 PNG / JPEG / WebP;不直接采信 provider 返回或下载响应头声明的类型,对象键扩展名由该内容类型派生。只有字节判不出来时才采信声明值,且声明值必须落在该槽位的白名单内(模型:`model/gltf-binary`、`model/gltf+json`、`model/fbx`、`application/x-fbx`;预览:`image/png`、`image/jpeg`、`image/jpg`、`image/webp`);两边都对不上就直接按上游内容不合法失败并退款,不做任何兜底 —— 放行 `text/plain` 这类未知类型只会落成「错的 content type + 拼出来的扩展名」。客户端不复制这份格式清单:画布只按「`assetKind=model3d` 且 `objectKey` 非空」放行,能否交给 3D 查看器由 `packages/model3d-viewer` 判定,判据依次是读接口声明的 `Content-Type`、字节魔数、地址扩展名,全判不出来即按 `unsupported-format` 报错。 +模型格式与体积由 `AssetObject` 承担(`content_type`、`content_length`、`content_hash`),因此不新增 `model_format`、`size_bytes`、`poly_count` 等列。两个槽位的 `content_type` 都在写入前按字节识别真实产物:模型按魔数认 GLB 的 `glTF` 头、FBX 的 `Kaydara FBX Binary` 头与 glTF 的 JSON 正文,预览按魔数认 PNG / JPEG / WebP;不直接采信 provider 返回或下载响应头声明的类型,对象键扩展名由该内容类型派生。只有字节判不出来时才采信声明值,且声明值必须落在该槽位的白名单内(模型:`model/gltf-binary`、`model/gltf+json`、`model/fbx`、`application/x-fbx`;预览:`image/png`、`image/jpeg`、`image/jpg`、`image/webp`);两边都对不上就直接按上游内容不合法失败并退款,不做任何兜底 —— 放行 `text/plain` 这类未知类型只会落成「错的 content type + 拼出来的扩展名」。客户端不复制这份格式清单:画布只按「`assetKind=model3d` 且 `objectKey` 非空」放行,能否交给 3D 查看器由 `packages/model3d-viewer` 判定,判据依次是读接口声明的 `Content-Type`、字节魔数、地址扩展名,全判不出来即按 `unsupported-format` 报错。这里的顺序是「信任后端的检测结果」:`content_type` 在后端写入前已经按字节核过,所以客户端以声明为先;字节魔数只兜住声明缺失或认不出来(例如 `application/octet-stream`)的情况,不负责纠正一个「认得出来但不对」的声明。 `external_generation_job.phase` 的取值集合不变,仍只允许现有两种执行阶段;阶段文案由 api-server 映射,不扩展 schema 常量。 diff --git a/packages/model3d-viewer/src/loader.ts b/packages/model3d-viewer/src/loader.ts index 7b122b6db..2e9264811 100644 --- a/packages/model3d-viewer/src/loader.ts +++ b/packages/model3d-viewer/src/loader.ts @@ -105,7 +105,7 @@ export function resolveModel3dViewerFormatFromMimeType( ); } -/** 按字节魔数识别格式;声明不可信时以它为准,识别不出返回 null。 */ +/** 按字节魔数识别格式;声明缺失或认不出来时才轮到它,识别不出返回 null。 */ export function resolveModel3dViewerFormatFromBytes( bytes: ArrayBuffer | Uint8Array, ): Model3DViewerFormat | null { @@ -139,8 +139,10 @@ export function resolveModel3dViewerFormatFromUrl( /** * 模型格式的判定顺序:声明 → 字节魔数 → 地址扩展名。 * - * 声明(响应内容类型 / OSS metadata / `asset_object.content_type`)是主线索,魔数兜住 - * 写歪的声明,扩展名是同源派生出来的最后一条线索。三处都判不出就返回 null,由加载流程 + * 声明(响应内容类型 / OSS metadata / `asset_object.content_type`)优先:后端的 + * `content_type` 在写入前已经按字节核过,客户端信任这份检测结果,不再自己纠正一个 + * 「认得出来但不对」的声明。魔数只在声明缺失或认不出来(例如 `application/octet-stream`) + * 时兜住,扩展名是同源派生出来的最后一条线索。三处都判不出就返回 null,由加载流程 * 报 `unsupported-format`,宿主把原因显示给用户 —— 不猜、不半渲染。 */ export function resolveModel3dViewerFormat({