From ded3f2f5377d06e465fa0b8ca71e9448f514799e Mon Sep 17 00:00:00 2001 From: huangrh Date: Mon, 16 Mar 2026 16:42:10 +0800 Subject: [PATCH] Add attachment download endpoint --- .../task/controller/TaskController.java | 25 +++++++++++++++++++ .../modules/task/service/TaskService.java | 14 +++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/controller/TaskController.java b/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/controller/TaskController.java index 9796efc..013e0c7 100644 --- a/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/controller/TaskController.java +++ b/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/controller/TaskController.java @@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.time.LocalDate; @@ -313,6 +315,29 @@ public class TaskController { .body(resource); } + @GetMapping("/reports/{id}/attachments/{attachmentId}") + @SaCheckRole(value = { "ADMIN", "AUDITOR", "USER" }, mode = SaMode.OR) + public ResponseEntity downloadAttachment( + @PathVariable("id") String id, + @PathVariable("attachmentId") Long attachmentId) { + com.chinaweal.youfool.reportdetect.modules.task.entity.AuditAttachment attachment = + taskService.getAttachment(id, attachmentId); + if (attachment == null || attachment.getFilepath() == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + File file = new File(attachment.getFilepath()); + if (!file.exists()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + String filename = attachment.getFilename() != null ? attachment.getFilename() : file.getName(); + String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8); + Resource resource = new FileSystemResource(file); + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(resource); + } + @GetMapping("/statistics") @SaCheckRole(value = { "ADMIN", "AUDITOR", "USER" }, mode = SaMode.OR) public ResponseEntity getStatistics() { diff --git a/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/service/TaskService.java b/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/service/TaskService.java index d5a2852..103ad29 100644 --- a/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/service/TaskService.java +++ b/src/main/java/com/chinaweal/youfool/reportdetect/modules/task/service/TaskService.java @@ -671,6 +671,20 @@ public class TaskService { return task != null ? task.getPdfPath() : null; } + public AuditAttachment getAttachment(String approvalId, Long attachmentId) { + if (approvalId == null || approvalId.isBlank() || attachmentId == null) { + return null; + } + Task task = taskRepository.findByApprovalId(approvalId); + if (task == null || task.getAttachments() == null) { + return null; + } + return task.getAttachments().stream() + .filter(a -> attachmentId.equals(a.getId())) + .findFirst() + .orElse(null); + } + public Map getStatistics() { List pendingStatuses = List.of("pending", "ocr_completed"); List auditedStatuses = List.of("compliant", "non-compliant");