格式判定的注释与文档改成「信任后端的检测结果」,不再说魔数纠正错误声明

- packages/model3d-viewer:`resolveModel3dViewerFormat` 与字节识别函数的注释改写——声明优先是因为后端的 `content_type` 写入前已按字节核过,魔数只在声明缺失或认不出来时兜住,不负责纠错一个认得出来但不对的声明
- docs/technical Tripo 集成方案:补上同一条口径,与实现里「声明 → 字节魔数 → 地址扩展名」的顺序对齐

行为不变,只改注释与文档。
This commit is contained in:
2026-09-24 19:51:25 +08:00
parent a61725003e
commit 2dfb60a34e
2 changed files with 6 additions and 4 deletions
@@ -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 常量。
+5 -3
View File
@@ -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({