package video_server import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "os" "path/filepath" "time" "FireLeave_tool/logger" ) // UploadToNginx 上传视频到 Nginx 服务器,返回 URL func UploadToNginx(filePath string, eventParams map[string]any, uploadURL string) (string, error) { logger.Logger.Printf("开始上传视频到 Nginx: %s → %s", filePath, uploadURL) // 打开文件 logger.Logger.Printf("打开文件: %s", filePath) startTime := time.Now() file, err := os.Open(filePath) if err != nil { logger.Logger.Printf("打开文件失败: %v, 耗时: %v", err, time.Since(startTime)) return "", fmt.Errorf("open file failed: %w", err) } defer file.Close() logger.Logger.Printf("文件打开成功, 耗时: %v", time.Since(startTime)) // 创建多部分表单 logger.Logger.Printf("创建多部分表单") body := new(bytes.Buffer) writer := multipart.NewWriter(body) // 创建表单文件字段 logger.Logger.Printf("创建表单文件字段: %s", filepath.Base(filePath)) part, err := writer.CreateFormFile("file", filepath.Base(filePath)) if err != nil { logger.Logger.Printf("创建表单文件字段失败: %v", err) return "", fmt.Errorf("create form file failed: %w", err) } // 复制文件内容到表单 logger.Logger.Printf("开始复制文件内容到表单") copyStartTime := time.Now() if _, err = io.Copy(part, file); err != nil { logger.Logger.Printf("复制文件内容失败: %v, 耗时: %v", err, time.Since(copyStartTime)) return "", fmt.Errorf("copy file failed: %w", err) } logger.Logger.Printf("文件内容复制成功, 耗时: %v", time.Since(copyStartTime)) // 序列化事件参数 logger.Logger.Printf("序列化事件参数") eventJSON, err := json.Marshal(eventParams) if err != nil { logger.Logger.Printf("序列化事件参数失败: %v", err) return "", fmt.Errorf("marshal event failed: %w", err) } logger.Logger.Printf("[Upload Event parameters]eventParams: %v", eventParams) logger.Logger.Printf("[Upload Event parameters]eventJSON: %s", string(eventJSON)) // 写入事件字段 logger.Logger.Printf("写入事件字段到表单") if err := writer.WriteField("event", string(eventJSON)); err != nil { logger.Logger.Printf("写入事件字段失败: %v", err) return "", fmt.Errorf("write event field failed: %w", err) } // 关闭表单写入器 logger.Logger.Printf("关闭表单写入器") if err := writer.Close(); err != nil { logger.Logger.Printf("关闭表单写入器失败: %v", err) return "", fmt.Errorf("close writer failed: %w", err) } logger.Logger.Printf("[HTTP Request]URL: %s", uploadURL) logger.Logger.Printf("[HTTP Request]Content-Type: %s", writer.FormDataContentType()) logger.Logger.Printf("[HTTP Request]Body 长度: %d bytes", body.Len()) // 创建HTTP请求 logger.Logger.Printf("创建HTTP请求") req, err := http.NewRequest("POST", uploadURL, body) if err != nil { logger.Logger.Printf("创建HTTP请求失败: %v", err) return "", fmt.Errorf("create request failed: %w", err) } req.Header.Set("Content-Type", writer.FormDataContentType()) // 发送HTTP请求 logger.Logger.Printf("发送HTTP请求到 Nginx") httpStartTime := time.Now() client := &http.Client{Timeout: 180 * time.Second} resp, err := client.Do(req) if err != nil { logger.Logger.Printf("发送HTTP请求失败: %v, 耗时: %v", err, time.Since(httpStartTime)) return "", fmt.Errorf("upload failed: %w", err) } defer resp.Body.Close() logger.Logger.Printf("HTTP请求发送成功, 耗时: %v", time.Since(httpStartTime)) // 读取响应 logger.Logger.Printf("读取HTTP响应") respStartTime := time.Now() respBody, _ := io.ReadAll(resp.Body) logger.Logger.Printf("响应读取完成, 耗时: %v", time.Since(respStartTime)) logger.Logger.Printf("[nginx response]Status: %d", resp.StatusCode) logger.Logger.Printf("[nginx response]Body: %s", string(respBody)) if resp.StatusCode != http.StatusOK { logger.Logger.Printf("Nginx返回错误状态码: %d", resp.StatusCode) return "", fmt.Errorf("nginx error %d: %s", resp.StatusCode, string(respBody)) } // 解析响应 logger.Logger.Printf("解析Nginx响应") var result struct { Code int `json:"code"` Result json.RawMessage `json:"result"` } if err := json.Unmarshal(respBody, &result); err != nil { logger.Logger.Printf("解析响应失败: %v", err) return "", fmt.Errorf("parse response failed: %w", err) } if result.Code != 0 { logger.Logger.Printf("Nginx返回错误代码: %d", result.Code) return "", fmt.Errorf("nginx error: %s", string(respBody)) } // 提取视频URL logger.Logger.Printf("提取视频URL") var videoURL string if err := json.Unmarshal(result.Result, &videoURL); err != nil { logger.Logger.Printf("提取视频URL失败: %v", err) return "", fmt.Errorf("extract video URL failed: %w", err) } logger.Logger.Printf("[ Upload Successful ] Local file: %s → Remote URL: %s", filePath, videoURL) logger.Logger.Printf("视频上传完成, 总耗时: %v", time.Since(startTime)) return videoURL, nil }