package com.rj.controller; import com.rj.service.IFaceDetectLogService; import com.rj.service.MinIOService; import com.rj.utils.MinIOUrlGenerator; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; import java.util.Map; /** * 图像检测控制器 */ @Slf4j @RestController @RequestMapping("/api/face-detect") @Tag(name = "图像检测", description = "图像检测相关接口") public class FaceDetectController { @Autowired private IFaceDetectLogService faceDetectLogService; @Autowired private MinIOService minioService; @Autowired private MinIOUrlGenerator urlGenerator; /** * 图像检测接口 */ @PostMapping("/detect") @Operation(summary = "图像检测", description = "检测图片中的图像信息") public ResponseEntity> detectFace( @Parameter(description = "图片URL", required = true) @RequestParam String imageUrl, @Parameter(description = "所属人姓名", required = false) @RequestParam(value = "ownerName", required = false) String ownerName, @Parameter(description = "所属人电话", required = false) @RequestParam(value = "ownerPhone", required = false) String ownerPhone, @Parameter(description = "模型名称", required = false) @RequestParam(value = "model", required = false) String model, @Parameter(description = "头像名称", required = false) @RequestParam(value = "avatarName", required = false) String avatarName) { Map result = new HashMap<>(); try { log.info("开始图像检测,图片URL: {}", imageUrl); // 执行图像检测 com.rj.entity.FaceDetectLog detectLog = faceDetectLogService.detectFaceAndSave(imageUrl, ownerName, ownerPhone, avatarName); result.put("success", detectLog.getSuccess()); result.put("message", detectLog.getSuccess() ? "图像检测成功" : "图像检测失败"); result.put("imageUrl", imageUrl); result.put("requestId", detectLog.getRequestId()); result.put("faceCount", detectLog.getFaceCount()); result.put("processingTimeMs", detectLog.getProcessingTimeMs()); result.put("ownerName", detectLog.getOwnerName()); result.put("ownerPhone", detectLog.getOwnerPhone()); result.put("avatarName", detectLog.getAvatarName()); if (!detectLog.getSuccess()) { result.put("errorMessage", detectLog.getErrorMessage()); return ResponseEntity.badRequest().body(result); } return ResponseEntity.ok(result); } catch (Exception e) { log.error("图像检测失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "图像检测失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } /** * 图像检测接口(JSON格式) */ @PostMapping("/detect-json") @Operation(summary = "图像检测(JSON)", description = "检测图片中的图像信息,支持JSON请求体") public ResponseEntity> detectFaceJson(@RequestBody Map requestBody) { Map result = new HashMap<>(); try { String imageUrl = requestBody.get("imageUrl"); String ownerName = requestBody.get("ownerName"); String ownerPhone = requestBody.get("ownerPhone"); String model = requestBody.get("model"); String avatarName = requestBody.get("avatarName"); if (imageUrl == null || imageUrl.trim().isEmpty()) { result.put("success", false); result.put("message", "图片URL不能为空"); return ResponseEntity.badRequest().body(result); } log.info("开始图像检测(JSON),图片URL: {}", imageUrl); // 执行图像检测 com.rj.entity.FaceDetectLog detectLog = faceDetectLogService.detectFaceAndSave(imageUrl, ownerName, ownerPhone, avatarName, model); result.put("success", detectLog.getSuccess()); result.put("message", detectLog.getSuccess() ? "图像检测成功" : "图像检测失败"); result.put("imageUrl", imageUrl); result.put("requestId", detectLog.getRequestId()); result.put("faceCount", detectLog.getFaceCount()); result.put("processingTimeMs", detectLog.getProcessingTimeMs()); result.put("ownerName", detectLog.getOwnerName()); result.put("ownerPhone", detectLog.getOwnerPhone()); result.put("avatarName", detectLog.getAvatarName()); result.put("model", detectLog.getModel()); if (!detectLog.getSuccess()) { result.put("errorMessage", detectLog.getErrorMessage()); return ResponseEntity.badRequest().body(result); } return ResponseEntity.ok(result); } catch (Exception e) { log.error("图像检测失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "图像检测失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } /** * 头衔上传接口 * 实现:文件上传 -> 生成短链接 -> 图像检测 */ @PostMapping("/avatar/upload") @Operation(summary = "头衔上传", description = "上传头像文件,生成短链接并进行图像检测") public ResponseEntity> uploadAvatar( @Parameter(description = "头像文件", required = true) @RequestParam("file") MultipartFile file, @Parameter(description = "用户ID", required = false) @RequestParam(value = "userId", required = false) String userId, @Parameter(description = "所属人姓名", required = false) @RequestParam(value = "ownerName", required = false) String ownerName, @Parameter(description = "所属人电话", required = false) @RequestParam(value = "ownerPhone", required = false) String ownerPhone, @Parameter(description = "头像名称", required = false) @RequestParam(value = "avatarName", required = false) String avatarName, @Parameter(description = "模型名称", required = false) @RequestParam(value = "model", required = false) String model, @Parameter(description = "短链接有效期(秒),默认1小时", required = false) @RequestParam(value = "expiresInSeconds", defaultValue = "3600") int expiresInSeconds) { Map result = new HashMap<>(); try { log.info("开始处理头衔上传,文件名: {}, 大小: {} bytes, 用户ID: {}", file.getOriginalFilename(), file.getSize(), userId); expiresInSeconds = 7*24*3600; // 默认7天 // 1. 验证文件 if (file.isEmpty()) { result.put("success", false); result.put("message", "文件不能为空"); return ResponseEntity.badRequest().body(result); } // 验证文件类型 String contentType = file.getContentType(); if (contentType == null || (!contentType.startsWith("image/"))) { result.put("success", false); result.put("message", "只支持图片文件格式"); return ResponseEntity.badRequest().body(result); } // 验证文件大小(限制为10MB,与Spring配置保持一致) if (file.getSize() > 10 * 1024 * 1024) { result.put("success", false); result.put("message", "文件大小不能超过10MB"); return ResponseEntity.badRequest().body(result); } // 2. 上传文件到MinIO log.info("开始上传文件到MinIO..."); String fileUrl = minioService.uploadFile(file); log.info("文件上传成功,URL: {}", fileUrl); // 3. 生成短链接(临时访问URL) log.info("开始生成短链接,有效期: {}秒", expiresInSeconds); String fileName = extractFileNameFromUrl(fileUrl); MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName, expiresInSeconds); if (!urlInfo.isSuccess()) { result.put("success", false); result.put("message", "生成短链接失败: " + urlInfo.getErrorMessage()); return ResponseEntity.internalServerError().body(result); } String shortUrl = urlInfo.getUrl(); log.info("短链接生成成功: {}", shortUrl); // 4. 进行图像检测 log.info("开始进行图像检测,使用模型: {}", model != null ? model : "默认模型"); com.rj.entity.FaceDetectLog detectLog = faceDetectLogService.detectFaceAndSave(shortUrl, ownerName, ownerPhone, avatarName, model); // 5. 构建响应结果 result.put("success", true); result.put("message", "头衔上传处理完成"); result.put("originalFileName", file.getOriginalFilename()); result.put("fileSize", file.getSize()); result.put("fileUrl", fileUrl); result.put("shortUrl", shortUrl); result.put("shortUrlExpiresAt", urlInfo.getFormattedExpiresAt()); result.put("shortUrlExpiresInSeconds", expiresInSeconds); result.put("userId", userId); result.put("ownerName", ownerName); result.put("ownerPhone", ownerPhone); result.put("avatarName", avatarName); result.put("model", model); // 图像检测结果 result.put("faceDetection", detectLog.toString()); if (!detectLog.getSuccess()) { result.put("faceDetectionError", detectLog.getErrorMessage()); log.warn("图像检测失败: {}", detectLog.getErrorMessage()); } else { log.info("图像检测成功,检测到 {} 张图像", detectLog.getFaceCount()); } log.info("头衔上传处理完成,文件URL: {}, 短链接: {}", fileUrl, shortUrl); return ResponseEntity.ok(result); } catch (Exception e) { log.error("头衔上传处理失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "头衔上传处理失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } /** * 从URL中提取文件名 */ private String extractFileNameFromUrl(String fileUrl) { if (fileUrl == null || fileUrl.isEmpty()) { return null; } // 从URL中提取文件名部分 // 例如: http://101.35.52.237:19005/car/filename.jpg -> filename.jpg int lastSlashIndex = fileUrl.lastIndexOf('/'); if (lastSlashIndex != -1 && lastSlashIndex < fileUrl.length() - 1) { return fileUrl.substring(lastSlashIndex + 1); } return fileUrl; } /** * 分页查询图像检测日志 */ @GetMapping("/logs") @Operation(summary = "分页查询图像检测日志", description = "分页查询图像检测日志列表") public ResponseEntity> getLogs( @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer current, @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size, @Parameter(description = "是否成功") @RequestParam(required = false) Boolean success, @Parameter(description = "开始时间") @RequestParam(required = false) String startTime, @Parameter(description = "结束时间") @RequestParam(required = false) String endTime, @Parameter(description = "所有人姓名") @RequestParam(required = false) String ownerName, @Parameter(description = "所有人电话") @RequestParam(required = false) String ownerPhone, @Parameter(description = "头像名字") @RequestParam(required = false) String avatarName) { Map result = new HashMap<>(); try { com.baomidou.mybatisplus.extension.plugins.pagination.Page page = faceDetectLogService.getPageList(current, size, success, startTime, endTime, ownerName, ownerPhone, avatarName); result.put("success", true); result.put("message", "查询成功"); result.put("data", page.getRecords()); result.put("total", page.getTotal()); result.put("current", page.getCurrent()); result.put("size", page.getSize()); result.put("pages", page.getPages()); return ResponseEntity.ok(result); } catch (Exception e) { log.error("查询图像检测日志失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "查询失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } /** * 根据ID查询图像检测日志详情 */ @GetMapping("/logs/{id}") @Operation(summary = "查询日志详情", description = "根据ID查询图像检测日志详情") public ResponseEntity> getLogById( @Parameter(description = "日志ID", required = true) @PathVariable Long id) { Map result = new HashMap<>(); try { log.info("查询图像检测日志详情,ID: {}", id); com.rj.entity.FaceDetectLog log = faceDetectLogService.getById(id); if (log != null) { result.put("success", true); result.put("message", "查询成功"); result.put("data", log); } else { result.put("success", false); result.put("message", "日志不存在"); } return ResponseEntity.ok(result); } catch (Exception e) { log.error("查询日志详情失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "查询失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } /** * 查询图像检测统计信息 */ @GetMapping("/statistics") @Operation(summary = "查询统计信息", description = "查询图像检测统计信息") public ResponseEntity> getStatistics( @Parameter(description = "开始时间") @RequestParam(required = false) String startTime, @Parameter(description = "结束时间") @RequestParam(required = false) String endTime) { Map result = new HashMap<>(); try { Map statistics = faceDetectLogService.getStatistics(startTime, endTime); result.put("success", true); result.put("message", "查询成功"); result.put("data", statistics); return ResponseEntity.ok(result); } catch (Exception e) { log.error("查询统计信息失败: {}", e.getMessage(), e); result.put("success", false); result.put("message", "查询失败: " + e.getMessage()); return ResponseEntity.internalServerError().body(result); } } }