Files
kenaito-media-picker/bug20260813.md
T
odboy f5e3f6b4ef fix: 修复媒体整理中的文件覆盖、BMP解析与重复整理问题
- 移动文件改用 uuid+原文件名,避免同名覆盖丢失数据
- BMP 负高度取绝对值,自顶向下格式解析正确
- 新增 {目录名}-picker 白名单输出目录,整理后跳过重复扫描
- 分类目录名去掉 uuid 前缀,重复运行并入已有目录
2025-03-15 21:17:24 +08:00

6.0 KiB
Raw Blame History

项目审查记录 2026-08-13

审查方式:静态代码审查(go build / go vet 均通过,此文件不含编译级错误) 审查范围:全部 .go 源码


一、严重 Bug

1. WEBP / BMP / PSB 永远进「读取异常」文件夹(专用分支是死代码)

  • 位置:util/image.go:9-19、core/handle_image.go:22,35,46
  • 问题:supportImageTypes 中包含了 .bmp、.webp、.psb,导致 handle_image.go:22 的通用分支总是先命中,调用 image.DecodeConfig(main.go:6-8 只注册了 png/jpeg/gif 解码器),对 webp/bmp 必然失败,文件全部落入「读取异常」目录。
  • 影响:handle_image.go:35(webp)、:46(bmp)的专用处理分支永远不会执行,与 README 承诺支持的格式不符。
  • 修复方向:从 supportImageTypes 中移除 .bmp / .webp / .psb,让专用分支生效;或在通用分支前先特判这三类格式。

2. PSD 从未被识别为图片,ImagePsdList 恒为空

  • 位置:core/file_scanner.go:70-79、core/handle_image.go:57
  • 问题:PSD 文件的 MIME 为 application/vnd.adobe.photoshop(不包含 image/ 前缀),且 .psd 不在 supportImageTypes 中,因此在 DoFilter 阶段就被丢弃,永远不会进入 GlobalImagePathList。
  • 影响:handle_image.go:57 的 PSD 分支不可达,README 声称的「PSD 单独归入图片_PSD」功能实际失效。
  • 修复方向:在过滤阶段对 .psd / application/vnd.adobe.photoshop 单独识别并入图片列表。

3. 同名文件移动时数据丢失风险(已处理)

  • 位置:util/video.go:152-169(moveFileToDir)
  • 问题:目标文件名只取 BaseName。不同子目录下的同名文件(如 a/photo.jpg、b/photo.jpg)会被移动到/复制到同一目标:Unix 下 os.Rename 静默覆盖,跨盘 fallback 的 copyFile(os.Create)也会截断覆盖目标。
  • 影响:真实数据丢失风险,且无任何告警。
  • 修复方向:目标名冲突时追加序号或 hash,确保不覆盖已有文件。

4. BMP 自顶向下格式(负高度)导致解析错乱(已处理)

  • 位置:core/bmp.go:59、core/handle_image.go:96-98
  • 问题:ReadBmpImage 直接返回 int32 宽高,负高度被 fmt.Sprintf("%d-%d") 拼成 "640--480",strings.Split("-") 后 width2Height[1] 为空串,String2int 返回 0,图片被错误归类。
  • 影响:此类 BMP 图片分辨率判定错误(高度变 0,全部按横屏普通处理)。
  • 修复方向:读取时对高度取绝对值,或改用不易混淆的分隔符/结构化存储。

5. 重复运行会重新整理已整理过的目录(已处理)

  • 位置:core/file_scanner.go:20、main.go
  • 问题:filepath.Walk 扫描整个根目录。第二次运行时,上次生成的 {uid}-图片_*、{uid}-视频_* 等目录会被再次扫描,其中已分类的文件会被再次移动,形成无限嵌套/重复归类。
  • 影响:重复执行程序导致目录结构越来越乱,违背 README「重复运行不会相互覆盖」的描述。
  • 修复方向:扫描时跳过已生成的 {uid}- 前缀目录,或提供过滤白名单。

二、次要问题

6. ffprobe 输出解析脆弱

  • 位置:util/video.go:53-101
  • 问题:对多视频流(常见于 MKV)的多行输出处理靠猜测(\r\n\r\n\r\n\r\n split、N/AxN/A 字符串替换等),且不校验 0 值分辨率,解析出错时归类到「普通」而非「读取异常」。

7. 视频「读取异常 / 已忽略」目录命名不一致

  • 位置:core/handle_video.go:56,62
  • 问题:这两个目录没有 uid 前缀(如 读取异常、已忽略),与其它 {uid}-视频_* 目录风格不统一,且与图片侧带 uid 的命名方式不一致。

8. 死代码 / 未使用数据

  • 位置:util/file.go:47-112、vars/video.go、util/file.go:17-21、vars/global.go:5
  • 问题:VideoPath2DurationMap / VideoPath2WidthHeightTagMap 赋值后从未使用(重命名逻辑已被注释掉);util/file.go 中保留大段注释代码;GetFileDirectory、GlobalFilePath2FileNameMap 未被使用。

9. doPickImageFile 空判断误报

  • 位置:core/handle_image.go:91
  • 问题:判断的是全局 vars.ImagePath2WidthHeightMap 而非入参 imagePath2WidthHeightMap;当所有图片都是错误/忽略时,会误打印「当前目录下没有扫描到图片文件」。

10. 目录创建失败未处理

  • 位置:core/handle_image.go(各 move*Image 函数)、core/handle_video.go(各 move*Video 函数)
  • 问题:多数 util.CreateDir 的返回值被忽略,若目录创建失败仍继续执行 DoMoveFileToDir,文件移动会静默失败。

11. 临时 ffprobe.exe 清理不保证

  • 位置:core/handle_video.go:13-24,68-71
  • 问题:通过流程末尾手动 os.Remove 清理,若中途异常(panic / 提前 return)会残留 ffprobe.exe;下次运行该文件会被扫描当作普通文件。建议 defer 清理。

三、优化建议

  1. 修复严重 bug 1/2 的关键:调整 supportImageTypes 列表 / 过滤逻辑,确保 webp、bmp、psb、psd 走各自正确的分支。
  2. 重复运行防护:扫描时跳过已生成的 {uid}- 目录。
  3. 合并 ffprobe 调用:分辨率 + 时长可用一次 -show_streams -show_format 取回,每视频省一次子进程创建。
  4. 消除重复代码:图片/视频各有约 60 个几乎相同的分组 + 移动函数,可用「分组名 → 列表」映射表驱动,大幅减小编码量。
  5. 使用 filepath.Join:代替 rootDir + separator + ... 字符串拼接,避免路径分隔符与平台问题。
  6. moveFileToDir 增加同名去重:冲突时追加序号/hash,杜绝覆盖。
  7. 清理死代码:删除注释掉的 rename 逻辑、未使用的 map 与函数。