From b1e6183dd1b0258929fb5cebcd237f27a0fdea75 Mon Sep 17 00:00:00 2001 From: litianxiang Date: Wed, 21 Jan 2026 14:34:43 +0800 Subject: [PATCH] =?UTF-8?q?GlobalAward=E6=8E=A5=E5=8F=A3token=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=EF=BC=8Cid=E6=9B=B4=E6=8D=A2=E4=B8=BAuuid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../da/controller/GlobalAwardController.java | 20 +++--- .../da/mapper/primary/entity/Contestant.java | 6 +- .../com/ai/da/model/dto/ContestantDTO.java | 10 +-- .../da/model/dto/UploadCompleteRequest.java | 14 +++++ .../ai/da/model/dto/UploadInitRequest.java | 9 ++- .../com/ai/da/service/GlobalAwardService.java | 2 + .../ai/da/service/upload/UploadService.java | 4 +- .../upload/impl/UploadServiceImpl.java | 63 ++++++++++++++++++- 8 files changed, 107 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/ai/da/controller/GlobalAwardController.java b/src/main/java/com/ai/da/controller/GlobalAwardController.java index b35de9fd..2158fcf7 100644 --- a/src/main/java/com/ai/da/controller/GlobalAwardController.java +++ b/src/main/java/com/ai/da/controller/GlobalAwardController.java @@ -76,7 +76,9 @@ public class GlobalAwardController { UploadCompleteResponse uploadCompleteResponse = uploadService.completePdfUpload( request.getUploadId(), request.getFileName(), - request.getTotalSize()); + request.getTotalSize(), + request.getEmail(), + request.getSecureToken()); return Response.success(uploadCompleteResponse); } @@ -123,7 +125,9 @@ public class GlobalAwardController { UploadCompleteResponse uploadCompleteResponse = uploadService.completeVideoUpload( request.getUploadId(), request.getFileName(), - request.getTotalSize()); + request.getTotalSize(), + request.getEmail(), + request.getSecureToken()); return Response.success(uploadCompleteResponse); } @@ -141,12 +145,12 @@ public class GlobalAwardController { return Response.success(globalAwardService.saveContestant(request)); } - @GetMapping("/contestants/by-email") - @ApiOperation(value = "根据邮箱查询参赛者", notes = "根据邮箱地址获取参赛者信息") - public Response getContestantByEmail(@ApiParam(value = "参赛者邮箱地址", required = true) @RequestParam("email") String email) { - ContestantDTO dto = globalAwardService.getContestantByEmail(email); - return Response.success(dto); - } +// @GetMapping("/contestants/by-email") +// @ApiOperation(value = "根据邮箱查询参赛者", notes = "根据邮箱地址获取参赛者信息") +// public Response getContestantByEmail(@ApiParam(value = "参赛者邮箱地址", required = true) @RequestParam("email") String email) { +// ContestantDTO dto = globalAwardService.getContestantByEmail(email); +// return Response.success(dto); +// } @GetMapping("/checkEmail") public Response checkEmail(@RequestParam("email") String email) { diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Contestant.java b/src/main/java/com/ai/da/mapper/primary/entity/Contestant.java index 353c6dda..8336faa5 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Contestant.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Contestant.java @@ -18,11 +18,11 @@ import java.time.LocalDateTime; @NoArgsConstructor @AllArgsConstructor @Builder -@TableName("submissions") +@TableName("contestants") public class Contestant { - @TableId(value = "id", type = IdType.AUTO) - private Long id; + @TableId(value = "id", type = IdType.ASSIGN_UUID) + private String id; private String email; diff --git a/src/main/java/com/ai/da/model/dto/ContestantDTO.java b/src/main/java/com/ai/da/model/dto/ContestantDTO.java index ebf5a22c..57342903 100644 --- a/src/main/java/com/ai/da/model/dto/ContestantDTO.java +++ b/src/main/java/com/ai/da/model/dto/ContestantDTO.java @@ -50,11 +50,11 @@ public class ContestantDTO { @ApiModelProperty(value = "视频文件路径", required = false, example = "contestants/user@example.com/2024/01/video_1234567890.mp4") private String videoPath; - /** - * 是否确认覆盖已存在记录(false 表示发现已有记录时仅返回 existingRecord,不覆盖) - */ - @ApiModelProperty(value = "是否确认覆盖已存在记录", required = false, example = "false") - private Boolean confirm = false; +// /** +// * 是否确认覆盖已存在记录(false 表示发现已有记录时仅返回 existingRecord,不覆盖) +// */ +// @ApiModelProperty(value = "是否确认覆盖已存在记录", required = false, example = "false") +// private Boolean confirm = false; @NotBlank private String secureToken; diff --git a/src/main/java/com/ai/da/model/dto/UploadCompleteRequest.java b/src/main/java/com/ai/da/model/dto/UploadCompleteRequest.java index 9817942f..abb7fb36 100644 --- a/src/main/java/com/ai/da/model/dto/UploadCompleteRequest.java +++ b/src/main/java/com/ai/da/model/dto/UploadCompleteRequest.java @@ -36,4 +36,18 @@ public class UploadCompleteRequest { @Positive(message = "文件大小必须大于0") @ApiModelProperty(value = "文件总大小(字节)", required = true, example = "10485760") private Long totalSize; + + /** + * 用户邮箱 + */ + @NotBlank(message = "用户邮箱不能为空") + @ApiModelProperty(value = "用户邮箱", required = true, example = "user@example.com") + private String email; + + /** + * 安全令牌(邮箱验证令牌) + */ + @NotBlank(message = "安全令牌不能为空") + @ApiModelProperty(value = "安全令牌", required = true, example = "abc123def456") + private String secureToken; } diff --git a/src/main/java/com/ai/da/model/dto/UploadInitRequest.java b/src/main/java/com/ai/da/model/dto/UploadInitRequest.java index 28e7e078..4b54770e 100644 --- a/src/main/java/com/ai/da/model/dto/UploadInitRequest.java +++ b/src/main/java/com/ai/da/model/dto/UploadInitRequest.java @@ -41,6 +41,13 @@ public class UploadInitRequest { /** * 用户邮箱 */ - @ApiModelProperty(value = "用户邮箱", required = false, example = "user@example.com") + @ApiModelProperty(value = "用户邮箱", required = true, example = "user@example.com") private String email; + + /** + * 安全令牌(邮箱验证令牌) + */ + @NotBlank(message = "安全令牌不能为空") + @ApiModelProperty(value = "安全令牌", required = true, example = "abc123def456") + private String secureToken; } diff --git a/src/main/java/com/ai/da/service/GlobalAwardService.java b/src/main/java/com/ai/da/service/GlobalAwardService.java index 48396e22..693cfcab 100644 --- a/src/main/java/com/ai/da/service/GlobalAwardService.java +++ b/src/main/java/com/ai/da/service/GlobalAwardService.java @@ -18,6 +18,8 @@ public interface GlobalAwardService { void checkEmail(String email); CheckOTPVO checkCode(String email, String otp); + + void checkSecurityToken(String email, String securityToken); } diff --git a/src/main/java/com/ai/da/service/upload/UploadService.java b/src/main/java/com/ai/da/service/upload/UploadService.java index 777495fe..e48cd304 100644 --- a/src/main/java/com/ai/da/service/upload/UploadService.java +++ b/src/main/java/com/ai/da/service/upload/UploadService.java @@ -37,7 +37,7 @@ public interface UploadService { * @param totalSize 文件总大小 * @return 完成上传结果 */ - UploadCompleteResponse completePdfUpload(String uploadId, String fileName, long totalSize); + UploadCompleteResponse completePdfUpload(String uploadId, String fileName, long totalSize, String email, String secureToken); /** * 查询PDF上传状态 @@ -74,7 +74,7 @@ public interface UploadService { * @param totalSize 文件总大小 * @return 完成上传结果 */ - UploadCompleteResponse completeVideoUpload(String uploadId, String fileName, long totalSize); + UploadCompleteResponse completeVideoUpload(String uploadId, String fileName, long totalSize, String email, String secureToken); /** * 查询视频上传状态 diff --git a/src/main/java/com/ai/da/service/upload/impl/UploadServiceImpl.java b/src/main/java/com/ai/da/service/upload/impl/UploadServiceImpl.java index a2659459..e68343cc 100644 --- a/src/main/java/com/ai/da/service/upload/impl/UploadServiceImpl.java +++ b/src/main/java/com/ai/da/service/upload/impl/UploadServiceImpl.java @@ -14,6 +14,7 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import java.io.FileInputStream; import java.io.IOException; @@ -62,16 +63,65 @@ public class UploadServiceImpl implements UploadService { @Value("${minio.bucketName:globalAward}") private String minioBucket; + @Resource + private com.ai.da.service.GlobalAwardService globalAwardService; + // 内存存储上传任务状态 private final ConcurrentHashMap uploadTasks = new ConcurrentHashMap<>(); // JSON序列化工具 private final ObjectMapper objectMapper = new ObjectMapper(); + /** + * 应用启动时加载现有上传任务 + */ + @PostConstruct + public void loadExistingTasks() { + try { + Path tempPath = Paths.get(tempDir); + if (!Files.exists(tempPath)) { + return; + } + + Files.list(tempPath) + .filter(Files::isDirectory) + .forEach(uploadDir -> { + try { + String uploadId = uploadDir.getFileName().toString(); + Path metadataPath = uploadDir.resolve("metadata.json"); + + if (Files.exists(metadataPath)) { + String json = Files.readString(metadataPath); + UploadTask task = objectMapper.readValue(json, UploadTask.class); + + // 检查任务是否已过期 + if (task.getExpiresAt().isAfter(LocalDateTime.now())) { + uploadTasks.put(uploadId, task); + log.info("加载现有上传任务: uploadId={}, status={}", uploadId, task.getStatus()); + } else { + // 清理过期任务 + cleanupTempFiles(uploadId); + log.info("清理过期上传任务: uploadId={}", uploadId); + } + } + } catch (Exception e) { + log.warn("加载上传任务失败: {}", uploadDir.getFileName(), e); + } + }); + + log.info("成功加载 {} 个现有上传任务", uploadTasks.size()); + } catch (Exception e) { + log.error("加载现有上传任务时发生错误", e); + } + } + // ===== PDF上传实现 ===== @Override public UploadTask initPdfUpload(UploadInitRequest request) { + // 验证安全令牌 + globalAwardService.checkSecurityToken(request.getEmail(), request.getSecureToken()); + // 验证PDF文件 validatePdfFile(request); @@ -115,7 +165,10 @@ public class UploadServiceImpl implements UploadService { } @Override - public UploadCompleteResponse completePdfUpload(String uploadId, String fileName, long totalSize) { + public UploadCompleteResponse completePdfUpload(String uploadId, String fileName, long totalSize, String email, String secureToken) { + // 验证安全令牌 + globalAwardService.checkSecurityToken(email, secureToken); + UploadTask task = validateAndGetTask(uploadId, "pdf"); log.info("开始PDF文件合并: uploadId={}, fileName={}", uploadId, fileName); @@ -175,6 +228,9 @@ public class UploadServiceImpl implements UploadService { @Override public UploadTask initVideoUpload(UploadInitRequest request) { + // 验证安全令牌 + globalAwardService.checkSecurityToken(request.getEmail(), request.getSecureToken()); + // 验证视频文件 validateVideoFile(request); @@ -218,7 +274,10 @@ public class UploadServiceImpl implements UploadService { } @Override - public UploadCompleteResponse completeVideoUpload(String uploadId, String fileName, long totalSize) { + public UploadCompleteResponse completeVideoUpload(String uploadId, String fileName, long totalSize, String email, String secureToken) { + // 验证安全令牌 + globalAwardService.checkSecurityToken(email, secureToken); + UploadTask task = validateAndGetTask(uploadId, "video"); log.info("开始视频文件合并: uploadId={}, fileName={}", uploadId, fileName);