Files
kenaito-media-picker/internal/mover/mover.go
T
odboy c266da2858 fix: 修复扫描/探测/移动三个健壮性问题
- scanner: filepath.Ext 替代 path.Ext,修复 Windows 点号目录名扩展名解析错误
- scanner: Walk 遇不可访问路径仅告警跳过,不再整体中止扫描
- probe: ffprobe 探测增加 30s 超时,避免损坏文件卡死程序
- mover: copyFile 失败时清理半截目标文件,消除双重 Close
- 新增代码审查报告 bug20260814.md
2025-04-07 21:00:37 +08:00

93 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package mover 负责文件的移动,跨文件系统时自动回退为复制后删除。
package mover
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/redmask-hb/GoSimplePrint/goPrint"
uuid "github.com/satori/go.uuid"
)
// Mover 文件移动器
type Mover struct{}
// MoveToDir 将一批文件移动到目标目录(目标文件名使用 uuid 前缀防止同名覆盖)。
// 返回移动成功的 源路径 → 目标目录 映射,供记录去向使用。
func (m *Mover) MoveToDir(filePaths []string, targetDir string) map[string]string {
moved := make(map[string]string)
if len(filePaths) == 0 {
return moved
}
if err := os.MkdirAll(targetDir, 0755); err != nil {
fmt.Printf("=== 创建目录失败: %s, 错误: %v\n", targetDir, err)
return moved
}
bar := goPrint.NewBar(100)
bar.SetNotice("=== 移动文件到目录:")
bar.SetGraph(">")
total := len(filePaths)
for i, src := range filePaths {
if moveOne(src, targetDir) {
moved[src] = targetDir
}
bar.PrintBar(percent(i+1, total))
}
bar.PrintEnd("=== Finish")
return moved
}
// moveOne 移动单个文件;跨文件系统时 fallback 为 copy+delete
func moveOne(src, targetDir string) bool {
fileName := strings.ReplaceAll(uuid.NewV4().String(), "-", "") + "_" + filepath.Base(src)
target := filepath.Join(targetDir, fileName)
if err := os.Rename(src, target); err == nil {
return true
}
if err := copyFile(src, target); err != nil {
fmt.Printf("=== 复制文件失败, 源: %s, 目标: %s, 错误: %v\n", src, target, err)
return false
}
if err := os.Remove(src); err != nil {
fmt.Printf("=== 删除源文件失败: %s, 错误: %v\n", src, err)
// 复制成功但删除失败,文件已存在于两处,视为移动成功
}
return true
}
// copyFile 逐块复制文件;失败时清理已写入的目标文件,避免残留半截文件
func copyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
if _, err := io.Copy(out, in); err != nil {
out.Close()
_ = os.Remove(dst)
return err
}
if err := out.Close(); err != nil {
_ = os.Remove(dst)
return err
}
return nil
}
// percent 计算百分比(0~100)
func percent(part, total int) int {
if total <= 0 {
return 100
}
return int(float64(part) / float64(total) * 100)
}