package handler import ( "encoding/json" "fmt" "os" "path/filepath" "video-inpaint/config" "video-inpaint/service" "github.com/gin-gonic/gin" ) type TaskHandler struct{} func (h *TaskHandler) Submit(c *gin.Context) { // 解析水印区域列表 regionsStr := c.PostForm("regions") if regionsStr == "" { Fail(c, "regions 参数不能为空") return } var regions []service.Region if err := json.Unmarshal([]byte(regionsStr), ®ions); err != nil { Fail(c, "regions 格式错误,需为 JSON 数组") return } if len(regions) == 0 { Fail(c, "至少需要一个水印区域") return } for i, r := range regions { if r.W <= 0 || r.H <= 0 { Fail(c, fmt.Sprintf("区域 %d 宽高必须大于 0", i)) return } } // 获取上传文件 file, err := c.FormFile("file") if err != nil { Fail(c, "未收到视频文件") return } maxMB := int64(500) if config.Cfg != nil && config.Cfg.Video.MaxUploadMB > 0 { maxMB = config.Cfg.Video.MaxUploadMB } if file.Size > maxMB*1024*1024 { Fail(c, fmt.Sprintf("文件过大,最大支持 %dMB", maxMB)) return } // 创建任务并确定存储路径 task := service.NewTask() tempDir := "./temp" if config.Cfg != nil && config.Cfg.Video.TempDir != "" { tempDir = config.Cfg.Video.TempDir } taskDir := filepath.Join(tempDir, task.TaskID) if err := os.MkdirAll(taskDir, 0755); err != nil { Fail(c, "创建任务目录失败") return } ext := filepath.Ext(file.Filename) if ext == "" { ext = ".mp4" } inputPath := filepath.Join(taskDir, "input"+ext) if err := c.SaveUploadedFile(file, inputPath); err != nil { os.RemoveAll(taskDir) Fail(c, "保存视频失败") return } // 异步启动处理 service.ProcessVideo(task, inputPath, regions) Success(c, "ok", gin.H{"task_id": task.TaskID}) } func (h *TaskHandler) Progress(c *gin.Context) { taskID := c.Query("task_id") if taskID == "" { Fail(c, "task_id 不能为空") return } task, ok := service.GetTask(taskID) if !ok { Fail(c, "任务不存在或已过期") return } Success(c, "ok", gin.H{ "task_id": task.TaskID, "status": task.Status, "progress": task.Progress, "message": task.Message, }) } func (h *TaskHandler) Download(c *gin.Context) { taskID := c.Query("task_id") if taskID == "" { Fail(c, "task_id 不能为空") return } task, ok := service.GetTask(taskID) if !ok { Fail(c, "任务不存在或已过期") return } if task.Status != service.StatusDone { Fail(c, "任务尚未完成") return } if task.OutputPath == "" || !fileExists(task.OutputPath) { Fail(c, "输出文件不存在") return } // 标记为已下载,让清理协程在延迟后删除 service.MarkDownloaded(taskID) c.FileAttachment(task.OutputPath, "clean_video.mp4") } func fileExists(path string) bool { _, err := os.Stat(path) return err == nil }