package api import ( "ZhenTuLocalPassiveAdapter/logger" "ZhenTuLocalPassiveAdapter/util" "context" "fmt" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) // UploadFaceDataWithProcessing 带图像处理的上传流程 // 根据服务器返回的配置处理图像后上传 func UploadFaceDataWithProcessing(ctx context.Context, scenicId int64, deviceNo string, faceImg, srcImg []byte, faceRect [4]int, facePos FacePositionInfo) error { // 1. 获取上传配置(包含图像处理配置) uploadConfig, err := GetUploadConfig(ctx, scenicId, deviceNo) if err != nil { logger.Error("获取上传配置失败", zap.String("deviceNo", deviceNo), zap.Error(err)) return err } logger.Info("获取到VIID任务ID", zap.Int64("taskId", uploadConfig.TaskID), zap.Bool("hasImageProcessing", uploadConfig.ImageProcessing != nil)) // 2. 将服务器配置转换为图像处理选项 imgOpts := configToImageOptions(uploadConfig.ImageProcessing) // 3. 处理图像 processedImages, err := util.ProcessImages(faceImg, srcImg, faceRect, imgOpts) if err != nil { SubmitFailure(ctx, uploadConfig.TaskID, "IMAGE_PROCESSING_FAILED", err.Error()) logger.Error("图像处理失败", zap.Int64("taskId", uploadConfig.TaskID), zap.Error(err)) return fmt.Errorf("image processing failed: %w", err) } logger.Debug("图像处理完成", zap.Int64("taskId", uploadConfig.TaskID), zap.Int("faceSize", len(processedImages.FaceData)), zap.Int("thumbSize", len(processedImages.ThumbData)), zap.Int("sourceSize", len(processedImages.SourceData))) // 4. 并行上传到OSS g, subCtx := errgroup.WithContext(ctx) // 上传人脸图 g.Go(func() error { if len(processedImages.FaceData) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.FaceUploadURL, processedImages.FaceData, "image/jpeg"); err != nil { return fmt.Errorf("upload face image failed: %w", err) } } return nil }) // 上传缩略图 g.Go(func() error { if len(processedImages.ThumbData) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.ThumbnailUploadURL, processedImages.ThumbData, "image/jpeg"); err != nil { return fmt.Errorf("upload thumbnail image failed: %w", err) } } return nil }) // 上传原图 g.Go(func() error { if len(processedImages.SourceData) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.SourceUploadURL, processedImages.SourceData, "image/jpeg"); err != nil { return fmt.Errorf("upload source image failed: %w", err) } } return nil }) if err := g.Wait(); err != nil { SubmitFailure(ctx, uploadConfig.TaskID, "UPLOAD_FAILED", err.Error()) logger.Error("文件上传失败", zap.Int64("taskId", uploadConfig.TaskID), zap.Error(err)) return err } // 5. 提交结果 if err := SubmitResult(ctx, uploadConfig.TaskID, facePos); err != nil { logger.Error("提交结果失败", zap.Int64("taskId", uploadConfig.TaskID), zap.Error(err)) return err } logger.Info("VIID任务完成", zap.Int64("taskId", uploadConfig.TaskID)) return nil } // configToImageOptions 将服务器配置转换为图像处理选项 func configToImageOptions(config *ImageProcessingConfig) *util.ImageProcessingOptions { // 应用默认值 effectiveConfig := config.GetEffectiveConfig() opts := &util.ImageProcessingOptions{ // 原图压缩配置 SourceCompressionEnabled: effectiveConfig.SourceCompression.Enabled, SourceQuality: effectiveConfig.SourceCompression.Quality, // 缩略图配置 ThumbnailMode: effectiveConfig.Thumbnail.Mode, ThumbnailShrinkRatio: effectiveConfig.Thumbnail.ShrinkRatio, ThumbnailQuality: effectiveConfig.Thumbnail.Quality, } return opts } // UploadFaceData 已有的上传流程(向后兼容) // 已废弃:请使用 UploadFaceDataWithProcessing func UploadFaceData(ctx context.Context, scenicId int64, deviceNo string, faceImg, thumbImg, srcImg []byte, facePos FacePositionInfo) error { // 1. 获取上传配置 uploadConfig, err := GetUploadConfig(ctx, scenicId, deviceNo) if err != nil { logger.Error("获取上传配置失败", zap.String("deviceNo", deviceNo), zap.Error(err)) return err } logger.Info("获取到VIID任务ID", zap.Int64("taskId", uploadConfig.TaskID)) // 2. 并行上传到OSS g, subCtx := errgroup.WithContext(ctx) // 上传人脸图 g.Go(func() error { if len(faceImg) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.FaceUploadURL, faceImg, "image/jpeg"); err != nil { return fmt.Errorf("upload face image failed: %w", err) } } return nil }) // 上传缩略图 g.Go(func() error { if len(thumbImg) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.ThumbnailUploadURL, thumbImg, "image/jpeg"); err != nil { return fmt.Errorf("upload thumbnail image failed: %w", err) } } return nil }) // 上传原图 g.Go(func() error { if len(srcImg) > 0 { if err := UploadFileToOSS(subCtx, uploadConfig.SourceUploadURL, srcImg, "image/jpeg"); err != nil { return fmt.Errorf("upload source image failed: %w", err) } } return nil }) if err := g.Wait(); err != nil { SubmitFailure(ctx, uploadConfig.TaskID, "UPLOAD_FAILED", err.Error()) logger.Error("文件上传失败", zap.Int64("taskId", uploadConfig.TaskID), zap.Error(err)) return err } // 3. 提交结果 if err := SubmitResult(ctx, uploadConfig.TaskID, facePos); err != nil { logger.Error("提交结果失败", zap.Int64("taskId", uploadConfig.TaskID), zap.Error(err)) return err } logger.Info("VIID任务完成", zap.Int64("taskId", uploadConfig.TaskID)) return nil }