Files
fire_leave_tool/video_server/video_upload.go
T
2026-07-03 20:55:15 +08:00

145 lines
5.2 KiB
Go

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)
fileName := filepath.Base(filePath)
// 打开文件
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", fileName)
part, err := writer.CreateFormFile("file", fileName)
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("[Nginx Multipart Detail] URL=%s file_field=file event_field=event filename=%s event_json=%s", uploadURL, fileName, 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
}