From fd0a37969ebbfd622094273a1ab6083ff241b2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 22 Sep 2026 13:50:29 +0800 Subject: [PATCH] =?UTF-8?q?3D=20=E4=BA=A7=E7=89=A9=E8=90=BD=E7=9B=98?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D=E8=A1=A5=E4=B8=8A=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - URL 无可用扩展名时按 content type 兜底,预览图不再写成 .glb - 文件名主干中性化路径分隔符与遍历片段,避免逃出目标目录 --- .../crates/platform-tripo/src/common/types.rs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/server-rs/crates/platform-tripo/src/common/types.rs b/server-rs/crates/platform-tripo/src/common/types.rs index 455779e29..327ac73a7 100644 --- a/server-rs/crates/platform-tripo/src/common/types.rs +++ b/server-rs/crates/platform-tripo/src/common/types.rs @@ -197,7 +197,42 @@ impl TripoDownloadedArtifact { && extension.len() <= MAX_ARTIFACT_FILE_EXTENSION_LEN && extension.bytes().all(|byte| byte.is_ascii_alphanumeric()) }) - .unwrap_or("glb"); - format!("{name}.{extension}") + .unwrap_or_else(|| fallback_artifact_extension(self.content_type.as_deref())); + format!("{}.{extension}", sanitize_artifact_file_stem(name)) + } +} + +/// URL 路径给不出可用扩展名时按 content type 兜底:同一条下载路径也服务预览图, +/// 一律写 `.glb` 会把 PNG / JPEG 产物写成模型文件名。 +fn fallback_artifact_extension(content_type: Option<&str>) -> &'static str { + let content_type = content_type.unwrap_or_default(); + if content_type.starts_with("image/png") { + "png" + } else if content_type.starts_with("image/jpeg") { + "jpg" + } else if content_type.starts_with("image/webp") { + "webp" + } else { + "glb" + } +} + +/// 文件名主干同样来自不可信输入:路径分隔符与 `..` 会让拼接结果逃出目标目录, +/// 这里统一中性化成安全字符。 +fn sanitize_artifact_file_stem(name: &str) -> String { + let sanitized: String = name + .chars() + .map(|ch| { + if ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_') { + ch + } else { + '_' + } + }) + .collect(); + if sanitized.trim_matches('_').is_empty() { + "artifact".to_string() + } else { + sanitized } }