diff --git a/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs b/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs index 207efb87d..b581a3ffd 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs @@ -1162,17 +1162,37 @@ fn publish_multipart_form( .map_err(|error| format!("构建发布资料 part 失败:{error}"))?, ); if let Some(cover) = media.cover.as_ref() { - form = form.part("cover", multipart_image_part(cover, "cover.png")?); + form = form.part( + "cover", + multipart_image_part( + cover, + &multipart_image_file_name("cover", cover.content_type), + )?, + ); } for (index, screenshot) in media.screenshots.iter().enumerate() { form = form.part( "screenshot", - multipart_image_part(screenshot, &format!("screenshot-{index}.png"))?, + multipart_image_part( + screenshot, + &multipart_image_file_name(&format!("screenshot-{index}"), screenshot.content_type), + )?, ); } Ok(form) } +/// multipart 文件名按真实内容类型给扩展名:JPEG/WebP 等不再一律叫 `.png`。 +/// +/// 服务端按 MIME part 判定,文件名只是给未来消费者看的事实;这里保持与 `content_type` 一致。 +fn multipart_image_file_name(part_name: &str, content_type: &str) -> String { + let extension = match content_type { + "image/jpeg" => "jpg", + other => other.strip_prefix("image/").unwrap_or("bin"), + }; + format!("{part_name}.{extension}") +} + fn multipart_image_part( image: &DraftImage, file_name: &str, @@ -1852,6 +1872,23 @@ mod tests { assert!(image_content_type("cover").is_err()); } + #[test] + fn multipart_image_file_name_follows_content_type() { + assert_eq!(multipart_image_file_name("cover", "image/png"), "cover.png"); + assert_eq!( + multipart_image_file_name("cover", "image/jpeg"), + "cover.jpg" + ); + assert_eq!( + multipart_image_file_name("screenshot-2", "image/webp"), + "screenshot-2.webp" + ); + assert_eq!( + multipart_image_file_name("screenshot-0", "application/octet-stream"), + "screenshot-0.bin" + ); + } + fn fixture_root(prefix: &str) -> std::path::PathBuf { static NEXT_TEST_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); let root = std::env::temp_dir().join(format!(