refactor: migrate SysFile to manage-file module
This commit is contained in:
@@ -27,6 +27,11 @@
|
|||||||
<artifactId>manage-notify</artifactId>
|
<artifactId>manage-notify</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.novalon.manage</groupId>
|
||||||
|
<artifactId>manage-file</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.novalon.manage</groupId>
|
<groupId>cn.novalon.manage</groupId>
|
||||||
<artifactId>manage-common</artifactId>
|
<artifactId>manage-common</artifactId>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package cn.novalon.manage.db.converter;
|
package cn.novalon.manage.db.converter;
|
||||||
|
|
||||||
import cn.novalon.manage.sys.core.domain.SysFile;
|
import cn.novalon.manage.file.core.domain.SysFile;
|
||||||
import cn.novalon.manage.db.entity.SysFileEntity;
|
import cn.novalon.manage.db.entity.SysFileEntity;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package cn.novalon.manage.db.repository;
|
package cn.novalon.manage.db.repository;
|
||||||
|
|
||||||
import cn.novalon.manage.sys.core.domain.SysFile;
|
import cn.novalon.manage.file.core.domain.SysFile;
|
||||||
import cn.novalon.manage.sys.core.repository.ISysFileRepository;
|
import cn.novalon.manage.file.core.repository.ISysFileRepository;
|
||||||
import cn.novalon.manage.db.converter.SysFileConverter;
|
import cn.novalon.manage.db.converter.SysFileConverter;
|
||||||
import cn.novalon.manage.db.dao.SysFileDao;
|
import cn.novalon.manage.db.dao.SysFileDao;
|
||||||
import cn.novalon.manage.db.entity.SysFileEntity;
|
import cn.novalon.manage.db.entity.SysFileEntity;
|
||||||
|
|||||||
+1
-7
@@ -1,13 +1,7 @@
|
|||||||
package cn.novalon.manage.sys.core.domain;
|
package cn.novalon.manage.file.core.domain;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件管理领域对象
|
|
||||||
*
|
|
||||||
* @author 张翔
|
|
||||||
* @date 2026-03-13
|
|
||||||
*/
|
|
||||||
public class SysFile {
|
public class SysFile {
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
+2
-8
@@ -1,15 +1,9 @@
|
|||||||
package cn.novalon.manage.sys.core.repository;
|
package cn.novalon.manage.file.core.repository;
|
||||||
|
|
||||||
import cn.novalon.manage.sys.core.domain.SysFile;
|
import cn.novalon.manage.file.core.domain.SysFile;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件仓储接口
|
|
||||||
*
|
|
||||||
* @author 张翔
|
|
||||||
* @date 2026-03-13
|
|
||||||
*/
|
|
||||||
public interface ISysFileRepository {
|
public interface ISysFileRepository {
|
||||||
|
|
||||||
Flux<SysFile> findByDeletedAtIsNullOrderByCreatedAtDesc();
|
Flux<SysFile> findByDeletedAtIsNullOrderByCreatedAtDesc();
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
package cn.novalon.manage.sys.core.service;
|
|
||||||
|
|
||||||
import cn.novalon.manage.sys.core.domain.SysFile;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
import org.springframework.http.codec.multipart.FilePart;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件服务接口
|
|
||||||
*
|
|
||||||
* @author 张翔
|
|
||||||
* @date 2026-03-13
|
|
||||||
*/
|
|
||||||
public interface ISysFileService {
|
|
||||||
Flux<SysFile> findAll();
|
|
||||||
Flux<SysFile> findByCreateBy(String createBy);
|
|
||||||
Mono<SysFile> findById(Long id);
|
|
||||||
Mono<SysFile> findByFileName(String fileName);
|
|
||||||
Mono<SysFile> upload(MultipartFile file, String createBy);
|
|
||||||
Mono<SysFile> uploadFilePart(FilePart filePart, String createBy);
|
|
||||||
Mono<Void> deleteById(Long id);
|
|
||||||
}
|
|
||||||
-105
@@ -1,105 +0,0 @@
|
|||||||
package cn.novalon.manage.sys.core.service.impl;
|
|
||||||
|
|
||||||
import cn.novalon.manage.sys.core.domain.SysFile;
|
|
||||||
import cn.novalon.manage.sys.core.repository.ISysFileRepository;
|
|
||||||
import cn.novalon.manage.sys.core.service.ISysFileService;
|
|
||||||
import org.springframework.http.codec.multipart.FilePart;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class SysFileService implements ISysFileService {
|
|
||||||
|
|
||||||
private final ISysFileRepository repository;
|
|
||||||
private final Path uploadPath = Paths.get("./uploads");
|
|
||||||
|
|
||||||
public SysFileService(ISysFileRepository repository) {
|
|
||||||
this.repository = repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Flux<SysFile> findAll() {
|
|
||||||
return repository.findByDeletedAtIsNullOrderByCreatedAtDesc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Flux<SysFile> findByCreateBy(String createBy) {
|
|
||||||
return repository.findByCreateByOrderByCreatedAtDesc(createBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<SysFile> findById(Long id) {
|
|
||||||
return repository.findById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<SysFile> findByFileName(String fileName) {
|
|
||||||
return repository.findByFilePathContaining(fileName)
|
|
||||||
.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<SysFile> upload(MultipartFile file, String createBy) {
|
|
||||||
try {
|
|
||||||
if (!Files.exists(uploadPath)) {
|
|
||||||
Files.createDirectories(uploadPath);
|
|
||||||
}
|
|
||||||
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
|
|
||||||
Path filePath = uploadPath.resolve(fileName);
|
|
||||||
Files.copy(file.getInputStream(), filePath);
|
|
||||||
|
|
||||||
SysFile sysFile = new SysFile();
|
|
||||||
sysFile.setFileName(file.getOriginalFilename());
|
|
||||||
sysFile.setFilePath(filePath.toString());
|
|
||||||
sysFile.setFileSize(String.valueOf(file.getSize()));
|
|
||||||
sysFile.setFileType(file.getContentType());
|
|
||||||
sysFile.setStorageType("local");
|
|
||||||
sysFile.setCreateBy(createBy);
|
|
||||||
sysFile.setCreatedAt(LocalDateTime.now());
|
|
||||||
|
|
||||||
return repository.save(sysFile);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return Mono.error(new RuntimeException("文件上传失败: " + e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> deleteById(Long id) {
|
|
||||||
return repository.deleteByIdAndDeletedAtIsNull(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<SysFile> uploadFilePart(FilePart filePart, String createBy) {
|
|
||||||
try {
|
|
||||||
if (!Files.exists(uploadPath)) {
|
|
||||||
Files.createDirectories(uploadPath);
|
|
||||||
}
|
|
||||||
String fileName = UUID.randomUUID() + "_" + filePart.filename();
|
|
||||||
Path filePath = uploadPath.resolve(fileName);
|
|
||||||
|
|
||||||
return filePart.transferTo(filePath.toFile())
|
|
||||||
.then(Mono.fromCallable(() -> {
|
|
||||||
SysFile sysFile = new SysFile();
|
|
||||||
sysFile.setFileName(filePart.filename());
|
|
||||||
sysFile.setFilePath(filePath.toString());
|
|
||||||
sysFile.setFileSize("0");
|
|
||||||
sysFile.setFileType(filePart.headers().getContentType().toString());
|
|
||||||
sysFile.setStorageType("local");
|
|
||||||
sysFile.setCreateBy(createBy);
|
|
||||||
sysFile.setCreatedAt(LocalDateTime.now());
|
|
||||||
return sysFile;
|
|
||||||
}))
|
|
||||||
.flatMap(sysFile -> repository.save(sysFile));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return Mono.error(new RuntimeException("文件上传失败: " + e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-184
@@ -1,184 +0,0 @@
|
|||||||
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.codec.multipart.FilePart;
|
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
|
||||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class SysFileHandler {
|
|
||||||
|
|
||||||
private final ISysFileService fileService;
|
|
||||||
|
|
||||||
public SysFileHandler(ISysFileService fileService) {
|
|
||||||
this.fileService = fileService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> getAllFiles(ServerRequest request) {
|
|
||||||
return ServerResponse.ok()
|
|
||||||
.body(fileService.findAll(), SysFile.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> getFileById(ServerRequest request) {
|
|
||||||
Long id = Long.valueOf(request.pathVariable("id"));
|
|
||||||
return fileService.findById(id)
|
|
||||||
.flatMap(file -> ServerResponse.ok().bodyValue(file))
|
|
||||||
.switchIfEmpty(ServerResponse.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> uploadFile(ServerRequest request) {
|
|
||||||
return request.multipartData()
|
|
||||||
.flatMap(data -> {
|
|
||||||
FilePart filePart = (FilePart) data.toSingleValueMap().get("file");
|
|
||||||
return ReactiveSecurityContextHolder.getContext()
|
|
||||||
.map(securityContext -> {
|
|
||||||
Object principal = securityContext.getAuthentication().getPrincipal();
|
|
||||||
if (principal instanceof Long) {
|
|
||||||
return principal.toString();
|
|
||||||
}
|
|
||||||
return "unknown";
|
|
||||||
})
|
|
||||||
.flatMap(createBy -> fileService.uploadFilePart(filePart, createBy))
|
|
||||||
.flatMap(file -> ServerResponse.status(HttpStatus.CREATED).bodyValue(file));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> downloadFile(ServerRequest request) {
|
|
||||||
Long id = Long.valueOf(request.pathVariable("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 ServerResponse.ok()
|
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
|
||||||
"attachment; filename=\"" + file.getFileName() + "\"")
|
|
||||||
.bodyValue(resource);
|
|
||||||
} else {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.switchIfEmpty(ServerResponse.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> downloadFileByName(ServerRequest request) {
|
|
||||||
String fileName = request.pathVariable("fileName");
|
|
||||||
return fileService.findByFileName(fileName)
|
|
||||||
.flatMap(file -> {
|
|
||||||
try {
|
|
||||||
Path filePath = Paths.get(file.getFilePath());
|
|
||||||
Resource resource = UrlResource.from(filePath.toUri());
|
|
||||||
|
|
||||||
if (resource.exists() && resource.isReadable()) {
|
|
||||||
return ServerResponse.ok()
|
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
|
||||||
"attachment; filename=\"" + file.getFileName() + "\"")
|
|
||||||
.bodyValue(resource);
|
|
||||||
} else {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.switchIfEmpty(ServerResponse.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> previewFile(ServerRequest request) {
|
|
||||||
Long id = Long.valueOf(request.pathVariable("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, java.nio.charset.StandardCharsets.UTF_8));
|
|
||||||
} else {
|
|
||||||
response.setPreviewType("unsupported");
|
|
||||||
response.setPreviewData(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ServerResponse.ok().bodyValue(response);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.switchIfEmpty(ServerResponse.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> previewFileByName(ServerRequest request) {
|
|
||||||
String fileName = request.pathVariable("fileName");
|
|
||||||
return fileService.findByFileName(fileName)
|
|
||||||
.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, java.nio.charset.StandardCharsets.UTF_8));
|
|
||||||
} else {
|
|
||||||
response.setPreviewType("unsupported");
|
|
||||||
response.setPreviewData(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ServerResponse.ok().bodyValue(response);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return ServerResponse.notFound().build();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.switchIfEmpty(ServerResponse.notFound().build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mono<ServerResponse> deleteFile(ServerRequest request) {
|
|
||||||
Long id = Long.valueOf(request.pathVariable("id"));
|
|
||||||
return fileService.deleteById(id)
|
|
||||||
.then(ServerResponse.noContent().build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user