From 5a4ac800184b1e554ca98dcd8d57777d6a474d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Thu, 12 Mar 2026 07:47:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0SysFileHandler?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86API(=E5=90=AB=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=A2=84=E8=A7=88)~?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sys/dto/response/FilePreviewResponse.java | 49 ++++++++ .../sys/handler/file/SysFileHandler.java | 117 ++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/FilePreviewResponse.java create mode 100644 novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/FilePreviewResponse.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/FilePreviewResponse.java new file mode 100644 index 0000000..1b8dd9a --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/dto/response/FilePreviewResponse.java @@ -0,0 +1,49 @@ +package cn.novalon.manage.sys.dto.response; + +public class FilePreviewResponse { + private String fileName; + private String fileType; + private Long fileSize; + private String previewType; + private String previewData; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileType() { + return fileType; + } + + public void setFileType(String fileType) { + this.fileType = fileType; + } + + public Long getFileSize() { + return fileSize; + } + + public void setFileSize(Long fileSize) { + this.fileSize = fileSize; + } + + public String getPreviewType() { + return previewType; + } + + public void setPreviewType(String previewType) { + this.previewType = previewType; + } + + public String getPreviewData() { + return previewData; + } + + public void setPreviewData(String previewData) { + this.previewData = previewData; + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java new file mode 100644 index 0000000..b334a05 --- /dev/null +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java @@ -0,0 +1,117 @@ +package cn.novalon.manage.sys.handler.file; + +import cn.novalon.manage.sys.core.domain.SysFile; +import cn.novalon.manage.sys.core.service.ISysFileService; +import cn.novalon.manage.sys.dto.response.FilePreviewResponse; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; + +@RestController +@RequestMapping("/api/files") +public class SysFileHandler { + + private final ISysFileService fileService; + + public SysFileHandler(ISysFileService fileService) { + this.fileService = fileService; + } + + @GetMapping + public Flux getAllFiles() { + return fileService.findAll(); + } + + @GetMapping("/{id}") + public Mono> getFileById(@PathVariable Long id) { + return fileService.findById(id) + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + + @PostMapping("/upload") + public Mono> uploadFile( + @RequestParam("file") MultipartFile file, + @RequestParam(value = "createBy", required = false) String createBy) { + return fileService.upload(file, createBy) + .map(f -> ResponseEntity.status(HttpStatus.CREATED).body(f)); + } + + @GetMapping("/{id}/download") + public Mono> downloadFile(@PathVariable Long id) { + return fileService.findById(id) + .flatMap(file -> { + try { + Path filePath = Paths.get(file.getFilePath()); + Resource resource = UrlResource.from(filePath.toUri()); + + if (resource.exists() && resource.isReadable()) { + return Mono.>just(ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=\"" + file.getFileName() + "\"") + .body(resource)); + } else { + return Mono.>just(ResponseEntity.notFound().build()); + } + } catch (Exception e) { + return Mono.>just(ResponseEntity.notFound().build()); + } + }) + .switchIfEmpty(Mono.>just(ResponseEntity.notFound().build())); + } + + @GetMapping("/{id}/preview") + public Mono> previewFile(@PathVariable Long id) { + return fileService.findById(id) + .flatMap(file -> { + try { + Path filePath = Paths.get(file.getFilePath()); + byte[] fileBytes = Files.readAllBytes(filePath); + + FilePreviewResponse response = new FilePreviewResponse(); + response.setFileName(file.getFileName()); + response.setFileType(file.getFileType()); + response.setFileSize((long) fileBytes.length); + + String fileType = file.getFileType().toLowerCase(); + if (fileType.startsWith("image/")) { + response.setPreviewType("image"); + response.setPreviewData(Base64.getEncoder().encodeToString(fileBytes)); + } else if (fileType.equals("application/pdf")) { + response.setPreviewType("pdf"); + response.setPreviewData(Base64.getEncoder().encodeToString(fileBytes)); + } else if (fileType.startsWith("text/")) { + response.setPreviewType("text"); + response.setPreviewData(new String(fileBytes)); + } else { + response.setPreviewType("unsupported"); + response.setPreviewData(null); + } + + return Mono.>just(ResponseEntity.ok(response)); + } catch (IOException e) { + return Mono.>just(ResponseEntity.notFound().build()); + } + }) + .switchIfEmpty(Mono.>just(ResponseEntity.notFound().build())); + } + + @DeleteMapping("/{id}") + public Mono> deleteFile(@PathVariable Long id) { + return fileService.deleteById(id) + .then(Mono.just(ResponseEntity.noContent().build())); + } +}