From f4fc1f26a77fa6605d5bfa066042d676f8e61b70 Mon Sep 17 00:00:00 2001 From: vladp Date: Sat, 4 Apr 2026 15:31:51 +0700 Subject: [PATCH] dev add load and download file for moderatuion user --- .../nocopy/controller/ApiController.java | 45 +++++- .../nocopy/controller/FileController.java | 30 +++- .../soune/nocopy/entity/file/FileStatus.java | 1 + .../moderation/ModerationPassportFile.java | 28 ++++ .../PassportModerationFileStatus.java | 17 ++ .../nocopy/handler/FileEntityHandler.java | 2 +- .../repository/ModerationFileRepository.java | 13 ++ .../service/file/FileEntityService.java | 24 ++- .../service/file/FileUploadService.java | 3 + .../soune/nocopy/service/file/ZipService.java | 146 ++++++++++++++++++ .../file/impl/FileUploadServiceImpl.java | 111 +++++++++---- .../moderation/ModerationFileService.java | 49 ++++++ .../file/moderation/ModerationFileStatus.java | 14 ++ 13 files changed, 440 insertions(+), 43 deletions(-) create mode 100644 src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationPassportFile.java create mode 100644 src/main/java/ru/soune/nocopy/entity/file/moderation/PassportModerationFileStatus.java create mode 100644 src/main/java/ru/soune/nocopy/repository/ModerationFileRepository.java create mode 100644 src/main/java/ru/soune/nocopy/service/file/ZipService.java create mode 100644 src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileService.java create mode 100644 src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileStatus.java diff --git a/src/main/java/ru/soune/nocopy/controller/ApiController.java b/src/main/java/ru/soune/nocopy/controller/ApiController.java index 73c505c..9ac7f92 100644 --- a/src/main/java/ru/soune/nocopy/controller/ApiController.java +++ b/src/main/java/ru/soune/nocopy/controller/ApiController.java @@ -35,11 +35,8 @@ import ru.soune.nocopy.repository.AuthTokenRepository; import ru.soune.nocopy.repository.FileEntityRepository; import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.service.FileSimilarityService; -import ru.soune.nocopy.service.file.CheckCounterService; -import ru.soune.nocopy.service.file.ProtectionsLimitService; +import ru.soune.nocopy.service.file.*; import ru.soune.nocopy.service.register.AuthService; -import ru.soune.nocopy.service.file.FileEntityService; -import ru.soune.nocopy.service.file.FileUploadService; import ru.soune.nocopy.util.FileUtil; import java.io.File; @@ -77,6 +74,8 @@ public class ApiController { private final CheckCounterService checkCounterService; + private final ZipService zipService; + @PostMapping("/v{version}/data") public ResponseEntity handlePostRequest(@RequestBody BaseRequest request, @PathVariable("version") int version) { @@ -165,6 +164,44 @@ public class ApiController { } } + @PostMapping("/v{version}/private/files/chunk") + public ResponseEntity uploadChunk( + @RequestParam(value = "upload_id", required = false) String uploadId, + @RequestParam(value = "chunk_number", required = false) Integer chunkNumber, + @RequestParam(value = "chunk", required = false) MultipartFile chunk, + @RequestParam(value = "last_file") Boolean last_file, + @RequestParam(value = "token") String token) { + try { + if (chunk == null || chunk.isEmpty()) { + return buildErrorResponse(uploadId, chunkNumber, "Chunk file null or empty"); + } + if (uploadId == null || uploadId.isBlank()) { + return buildErrorResponse(uploadId, chunkNumber, "Upload Id is required"); + } + if (chunkNumber == null || chunkNumber < 0) { + return buildErrorResponse(uploadId, chunkNumber, "Valid chunk number is required"); + } + + Long userId = authService.useUserAuthToken(token); + + UploadProgressResponse uploadProgressResponse = fileUploadService.uploadPassportChunk(uploadId, chunkNumber, + chunk, userId); + + if (last_file) { + zipService.createAndSplitZip(userId, + fileEntityService.getAllUserFiles(userId, List.of(FileStatus.PRIVATE))); + } + + return buildSuccessResponse(uploadId, chunkNumber, chunk, + fileEntityService.findFileIdByPath(uploadProgressResponse.getFilePath())); + }catch (FileFormatException e){ + return buildErrorResponse(uploadId, chunkNumber, e.getMessage()); + } catch (Exception e) { + log.error("Error uploading chunk", e); + return buildErrorResponse(uploadId, chunkNumber, "Failed to upload chunk: " + e.getMessage()); + } + } + private final NoCopyFileService noCopyFileService; @GetMapping("/v{version}/files/{fileId}/similar") diff --git a/src/main/java/ru/soune/nocopy/controller/FileController.java b/src/main/java/ru/soune/nocopy/controller/FileController.java index 6beca5a..38cf43e 100644 --- a/src/main/java/ru/soune/nocopy/controller/FileController.java +++ b/src/main/java/ru/soune/nocopy/controller/FileController.java @@ -2,8 +2,8 @@ package ru.soune.nocopy.controller; import com.vrt.NoCopyFileService; import com.vrt.fileprotection.FileProtector; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; @@ -17,6 +17,7 @@ import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.service.file.CheckCounterService; import ru.soune.nocopy.service.file.FileStorageService; import ru.soune.nocopy.service.file.ImageResizeService; +import ru.soune.nocopy.service.file.ZipService; import ru.soune.nocopy.util.FileUtil; import java.io.FileNotFoundException; @@ -31,29 +32,25 @@ import java.nio.file.Paths; @RestController @RequestMapping("/api/files") @Slf4j +@AllArgsConstructor public class FileController { - @Autowired private FileStorageService fileStorageService; - @Autowired private FileEntityRepository fileRepository; - @Autowired private CheckCounterService checkCounterService; - @Autowired private UserRepository userRepository; - @Autowired private ImageResizeService imageResizeService; - @Autowired private NoCopyFileService noCopyFileService; - @Autowired private FileUtil fileUtil; + private ZipService zipService; + @GetMapping("/public/{fileId}") public ResponseEntity getPublicFile(@PathVariable String fileId) { try { @@ -166,4 +163,21 @@ public class FileController { .ok() .body(fileInfo); } + + @GetMapping("/download/user-passport/archive/{userId}") + public ResponseEntity downloadPassportZip(@PathVariable Long userId) { + try { + byte[] zipBytes = zipService.assembleZipFromSplitFiles(userId); + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=passport_" + userId + ".zip") + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .contentLength(zipBytes.length) + .body(zipBytes); + } catch (IOException e) { + log.error("Failed to assemble passport for user {}", userId, e); + return ResponseEntity.internalServerError().build(); + } + } } diff --git a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java index a23ead9..48d5611 100644 --- a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java +++ b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java @@ -10,5 +10,6 @@ public enum FileStatus { TEMP, REMOVED, MODERATION, + PRIVATE, BLOCKED } diff --git a/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationPassportFile.java b/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationPassportFile.java new file mode 100644 index 0000000..5556410 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationPassportFile.java @@ -0,0 +1,28 @@ +package ru.soune.nocopy.entity.file.moderation; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@Table(name = "moderation_file") +@Getter @Setter +@AllArgsConstructor +@NoArgsConstructor +public class ModerationPassportFile { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false) + private Long userId; + + @Column(name = "path", nullable = false) + private String path; + + @Column(name = "part") + private Integer part; + + private String status; +} diff --git a/src/main/java/ru/soune/nocopy/entity/file/moderation/PassportModerationFileStatus.java b/src/main/java/ru/soune/nocopy/entity/file/moderation/PassportModerationFileStatus.java new file mode 100644 index 0000000..8cc8beb --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/file/moderation/PassportModerationFileStatus.java @@ -0,0 +1,17 @@ +package ru.soune.nocopy.entity.file.moderation; + +import lombok.Getter; + +@Getter +public enum PassportModerationFileStatus { + + DOWNLOAD("download"), + ON_MODERATION("on_moderation"), + MODERATED("moderated"); + + private final String name; + + PassportModerationFileStatus(String name) { + this.name = name; + } +} diff --git a/src/main/java/ru/soune/nocopy/handler/FileEntityHandler.java b/src/main/java/ru/soune/nocopy/handler/FileEntityHandler.java index 660ee7c..9384498 100644 --- a/src/main/java/ru/soune/nocopy/handler/FileEntityHandler.java +++ b/src/main/java/ru/soune/nocopy/handler/FileEntityHandler.java @@ -222,7 +222,7 @@ public class FileEntityHandler implements RequestHandler { return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), - FileEntityResponse.builder().status(newStatus).build()); + Map.of("file_status", newStatus, "file_id", fileId)); } private BaseResponse handleSearchFiles(BaseRequest request, FileEntityRequest fileRequest) { diff --git a/src/main/java/ru/soune/nocopy/repository/ModerationFileRepository.java b/src/main/java/ru/soune/nocopy/repository/ModerationFileRepository.java new file mode 100644 index 0000000..6ad4167 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/repository/ModerationFileRepository.java @@ -0,0 +1,13 @@ +package ru.soune.nocopy.repository; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import ru.soune.nocopy.entity.file.moderation.ModerationPassportFile; + +import java.util.List; + +@Repository +public interface ModerationFileRepository extends CrudRepository { + + public List findByStatus(String status); +} diff --git a/src/main/java/ru/soune/nocopy/service/file/FileEntityService.java b/src/main/java/ru/soune/nocopy/service/file/FileEntityService.java index bb70f14..441cf53 100644 --- a/src/main/java/ru/soune/nocopy/service/file/FileEntityService.java +++ b/src/main/java/ru/soune/nocopy/service/file/FileEntityService.java @@ -77,12 +77,28 @@ public class FileEntityService { for (Long uId : userRepository.findByCompanyId(user.getCompany().getId()).stream() .map(User::getId) .toList()) { - allFiles.addAll(fileEntityRepository.findByUserIdAndStatusIn(uId, - List.of(FileStatus.ACTIVE, FileStatus.BLOCKED, FileStatus.MODERATION))); + allFiles.addAll(getAllUserFiles(uId, List.of(FileStatus.ACTIVE, FileStatus.BLOCKED, + FileStatus.MODERATION))); } } else { - allFiles = fileEntityRepository.findByUserIdAndStatusIn(userId, - List.of(FileStatus.ACTIVE, FileStatus.BLOCKED, FileStatus.MODERATION)); + allFiles = getAllUserFiles(userId, List.of(FileStatus.ACTIVE, FileStatus.BLOCKED, FileStatus.MODERATION)); + } + + return allFiles; + } + + public List getAllUserFiles(Long userId, List statuses) { + User user = userRepository.findById(userId).orElseThrow(); + List allFiles = new ArrayList<>(); + + if (user.getCompany() != null) { + for (Long uId : userRepository.findByCompanyId(user.getCompany().getId()).stream() + .map(User::getId) + .toList()) { + allFiles.addAll(fileEntityRepository.findByUserIdAndStatusIn(uId, statuses)); + } + } else { + allFiles = fileEntityRepository.findByUserIdAndStatusIn(userId, statuses); } return allFiles; diff --git a/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java b/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java index f1d94d3..88eb125 100644 --- a/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java +++ b/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java @@ -17,6 +17,9 @@ public interface FileUploadService { UploadProgressResponse uploadChunk(String uploadId, Integer chunkNumber, MultipartFile chunkFile, Integer findSimilar); + UploadProgressResponse uploadPassportChunk(String uploadId, Integer chunkNumber, MultipartFile chunkFile, + Long userId); + UploadProgressResponse getUploadProgress(String uploadId); void completeFileProcessingAsync(FileUploadSession session, FileStatus status); diff --git a/src/main/java/ru/soune/nocopy/service/file/ZipService.java b/src/main/java/ru/soune/nocopy/service/file/ZipService.java new file mode 100644 index 0000000..abc1a07 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/file/ZipService.java @@ -0,0 +1,146 @@ +package ru.soune.nocopy.service.file; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.soune.nocopy.entity.file.FileEntity; +import ru.soune.nocopy.entity.file.moderation.ModerationPassportFile; +import ru.soune.nocopy.service.file.moderation.ModerationFileService; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +@Service +@Slf4j +@RequiredArgsConstructor +public class ZipService { + + private final ModerationFileService moderationFileService; + + private static final int MAX_SIZE_MB = 20; + + private static final int FIRST_PART = 1; + + private static final int SECOND_PART = 2; + + public void createAndSplitZip(Long userId, List files) throws IOException { + byte[] zipBytes = createZip(files); + String base64String = Base64.getEncoder().encodeToString(zipBytes); + String[] parts = splitBase64(base64String); + saveSplitFiles(userId, parts[0], parts[1]); + } + + public byte[] assembleZipFromSplitFiles(Long userId) throws IOException { + List activeFiles = moderationFileService.getActiveFiles(); + + String part1Content = null; + String part2Content = null; + + for (ModerationPassportFile file : activeFiles) { + Path filePath = Paths.get(file.getPath()); + String content = Files.readString(filePath); + + if (file.getPart() == FIRST_PART) { + part1Content = content; + } else if (file.getPart() == SECOND_PART) { + part2Content = content; + } + } + + if (part1Content == null || part2Content == null) { + throw new IOException("Missing part 1 or part 2 for user: " + userId); + } + + String base64String = mergeBase64(part1Content, part2Content); + + return Base64.getDecoder().decode(base64String); + } + + private byte[] createZip(List files) throws IOException { + long totalSize = files.stream() + .map(FileEntity::getFileSize) + .reduce(0L, Long::sum); + + + if (totalSize > MAX_SIZE_MB * 1024 * 1024) { + throw new IllegalArgumentException( + String.format("Total size %.2f MB exceeds %d MB limit", + totalSize / (1024.0 * 1024.0), MAX_SIZE_MB) + ); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + + for (FileEntity file: files) { + String filePath = file.getFilePath(); + String fileName = file.getStoredFileName(); + + Path path = Paths.get(filePath); + ZipEntry zipEntry = new ZipEntry(fileName); + zos.putNextEntry(zipEntry); + Files.copy(path, zos); + zos.closeEntry(); + + log.info("Added file {} to ZIP", fileName); + } + } + + return baos.toByteArray(); + } + + private String[] splitBase64(String base64) { + StringBuilder part1 = new StringBuilder(); + StringBuilder part2 = new StringBuilder(); + + for (int i = 0; i < base64.length(); i++) { + if (i % 2 == 0) { + part1.append(base64.charAt(i)); + } else { + part2.append(base64.charAt(i)); + } + } + + return new String[]{part1.toString(), part2.toString()}; + } + + private void saveSplitFiles(Long userId, String part1, String part2) throws IOException { + Path userDir = Paths.get("/uploads/passport", String.valueOf(userId)); + Files.createDirectories(userDir); + + Path file1 = userDir.resolve(userId + "___1.txt"); + Files.writeString(file1, part1); + Path file2 = userDir.resolve(userId + "___2.txt"); + Files.writeString(file2, part2); + Map files = Map.of(FIRST_PART, file1.toString(), SECOND_PART, file2.toString()); + + moderationFileService.addFiles(userId, files); + + log.info("Saved split files: {} and {}", file1, file2); + } + + private String mergeBase64(String part1, String part2) { + StringBuilder merged = new StringBuilder(); + + int maxLength = Math.max(part1.length(), part2.length()); + + for (int i = 0; i < maxLength; i++) { + if (i < part1.length()) { + merged.append(part1.charAt(i)); + } + if (i < part2.length()) { + merged.append(part2.charAt(i)); + } + } + + return merged.toString(); + } +} diff --git a/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java b/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java index 53e7c76..4693cab 100644 --- a/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java +++ b/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java @@ -27,7 +27,9 @@ import ru.soune.nocopy.service.ImageHashService; import ru.soune.nocopy.service.cost.CostService; import ru.soune.nocopy.service.file.FileEntityService; import ru.soune.nocopy.service.file.FileUploadService; +import ru.soune.nocopy.service.file.moderation.ModerationFileService; import ru.soune.nocopy.service.notification.NotificationService; +import ru.soune.nocopy.service.register.AuthService; import ru.soune.nocopy.service.tariff.TariffInfoService; import ru.soune.nocopy.util.FileUtil; @@ -88,6 +90,10 @@ public class FileUploadServiceImpl implements FileUploadService { private final NotificationService notificationService; + private final AuthService authService; + + private final ModerationFileService moderationFileService; + @PostConstruct public void init() { try { @@ -189,31 +195,24 @@ public class FileUploadServiceImpl implements FileUploadService { FileUploadSession session = sessionRepository.findById(uploadId) .orElseThrow(() -> new UploadSessionNotFoundException(uploadId)); - validateSession(session); - - if (session.getExpiresAt().isBefore(LocalDateTime.now())) { - handleExpiredSession(session); - throw new FileUploadException("Upload session expired"); - } - - if (chunkNumber < 0 || chunkNumber >= session.getTotalChunks()) { - throw new FileUploadException( - String.format("Invalid chunk number %d. Expected number: %d", - chunkNumber, session.getTotalChunks() - 1)); - } - - if (chunkNumber == 0 && chunkFile.getSize() > chunkSize || chunkNumber + 1 == (session.getTotalChunks()) - && chunkFile.getSize() > chunkSize) { - throw new ChunkSizeExceededException(chunkFile.getSize(), chunkSize); - } - - if (chunkNumber > 0 && chunkNumber + 1 < session.getTotalChunks() && chunkFile.getSize() != chunkSize) { - throw new ChunkSizeExceededException(chunkFile.getSize(), chunkSize); - } + validateSession(session, chunkNumber, chunkFile); return processChunk(session, chunkNumber, chunkFile, findSimilar); } + @Override + public UploadProgressResponse uploadPassportChunk(String uploadId, Integer chunkNumber, MultipartFile chunkFile, + Long userId) { + FileUploadSession session = sessionRepository.findById(uploadId).orElseThrow(() -> + new UploadSessionNotFoundException(uploadId)); + + validateSession(session, chunkNumber, chunkFile); + + UploadProgressResponse uploadProgressResponse = processChunk(session, chunkNumber, chunkFile); + + return uploadProgressResponse; + } + @Override public UploadProgressResponse getUploadProgress(String uploadId) { FileUploadSession session = sessionRepository.findById(uploadId) @@ -246,7 +245,7 @@ public class FileUploadServiceImpl implements FileUploadService { FileEntity saved = fileEntityRepository.save(fileEntity); - if (session.getFileType().equals("image")) { + if (session.getFileType().equals("image") && status != FileStatus.PRIVATE) { Map hash = imageHashService.calculateHash(filePath); imageHashService.create(saved, hash); @@ -254,21 +253,21 @@ public class FileUploadServiceImpl implements FileUploadService { cleanupSessionFiles(session); - if (status != FileStatus.TEMP) { + if (status != FileStatus.TEMP && status != FileStatus.PRIVATE) { FileProtector.FileInfo fileInfo = fileUtil.createFileInfo(fileEntity, session.getConvertTo()); noCopyFileService.addFile(fileInfo); } log.info("File processing completed for session: {}", session.getUploadId()); - } catch (Exception e) { log.error("Failed to complete file processing for session {}: {}", session.getUploadId(), e.getMessage(), e); } } - private void validateSession(FileUploadSession session) { + private void validateSession(FileUploadSession session, Integer chunkNumber, + MultipartFile chunkFile) { UploadStatus status = session.getStatus(); if (status == UploadStatus.FAILED) { @@ -295,6 +294,67 @@ public class FileUploadServiceImpl implements FileUploadService { session.setStatus(UploadStatus.UPLOADING); sessionRepository.save(session); } + + if (session.getExpiresAt().isBefore(LocalDateTime.now())) { + handleExpiredSession(session); + throw new FileUploadException("Upload session expired"); + } + + if (chunkNumber < 0 || chunkNumber >= session.getTotalChunks()) { + throw new FileUploadException( + String.format("Invalid chunk number %d. Expected number: %d", + chunkNumber, session.getTotalChunks() - 1)); + } + + if (chunkNumber == 0 && chunkFile.getSize() > chunkSize || chunkNumber + 1 == (session.getTotalChunks()) + && chunkFile.getSize() > chunkSize) { + throw new ChunkSizeExceededException(chunkFile.getSize(), chunkSize); + } + + if (chunkNumber > 0 && chunkNumber + 1 < session.getTotalChunks() && chunkFile.getSize() != chunkSize) { + throw new ChunkSizeExceededException(chunkFile.getSize(), chunkSize); + } + } + + private UploadProgressResponse processChunk(FileUploadSession session, Integer chunkNumber, MultipartFile chunkFile) { + String chunkPath = null; + + try { + chunkPath = saveChunkWithIntegrityCheck(session, chunkNumber, chunkFile); + + session.getChunkPaths().put(chunkNumber, chunkPath); + session.setChunksUploaded(session.getChunksUploaded() + 1); + session.setStatus(UploadStatus.UPLOADING); + session.setExpiresAt(LocalDateTime.now().plusMinutes(1)); + + boolean isLastChunk = session.getChunksUploaded().equals(session.getTotalChunks()); + + if (isLastChunk) { + String finalFilePath = assembleFileSynchronously(session); + + session.setStatus(UploadStatus.COMPLETED); + session.setFilePath(finalFilePath); + + completeFileProcessingAsync(session, FileStatus.PRIVATE); + } else { + sessionRepository.save(session); + } + + return UploadProgressResponse.fromSession(session); + } catch (Exception e) { + if (chunkPath != null) { + cleanupFailedChunk(chunkPath); + } + + log.error("Failed to process chunk {} for session {}: {}", + chunkNumber, session.getUploadId(), e.getMessage(), e); + + session.setStatus(UploadStatus.FAILED); + session.setLastError(e.getMessage()); + sessionRepository.save(session); + + throw new FileUploadException("Failed to upload chunk: " + e.getMessage(), e); + } } private UploadProgressResponse processChunk(FileUploadSession session, Integer chunkNumber, MultipartFile chunkFile, @@ -378,7 +438,6 @@ public class FileUploadServiceImpl implements FileUploadService { completeFileProcessingAsync(session, status); - if (status != FileStatus.TEMP) { String fileType = session.getFileType(); diff --git a/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileService.java b/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileService.java new file mode 100644 index 0000000..57e462c --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileService.java @@ -0,0 +1,49 @@ +package ru.soune.nocopy.service.file.moderation; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.soune.nocopy.entity.file.moderation.ModerationPassportFile; +import ru.soune.nocopy.repository.ModerationFileRepository; + +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class ModerationFileService { + + private final ModerationFileRepository moderationFileRepository; + + public void addFiles(Long userId, Map files) { + List moderationFileRepositoryByStatus = + moderationFileRepository.findByStatus(ModerationFileStatus.ACTIVE.getName()); + + if (!moderationFileRepositoryByStatus.isEmpty()) { + disActiveDocuments(moderationFileRepositoryByStatus); + } + + for (Map.Entry file : files.entrySet()) { + ModerationPassportFile moderationFile = ModerationPassportFile.builder().userId(userId) + .path(file.getValue()) + .part(file.getKey()) + .userId(userId) + .status(ModerationFileStatus.ACTIVE.getName()) + .build(); + + + moderationFileRepository.save(moderationFile); + } + } + + public List getActiveFiles() { + return moderationFileRepository.findByStatus(ModerationFileStatus.ACTIVE.getName()); + } + + private void disActiveDocuments(List moderationFileRepositoryByStatus) { + for (ModerationPassportFile moderationFile : moderationFileRepositoryByStatus) { + moderationFile.setStatus(ModerationFileStatus.NOT_ACTIVE.getName()); + + moderationFileRepository.save(moderationFile); + } + } +} diff --git a/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileStatus.java b/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileStatus.java new file mode 100644 index 0000000..8dc3052 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/file/moderation/ModerationFileStatus.java @@ -0,0 +1,14 @@ +package ru.soune.nocopy.service.file.moderation; + +import lombok.Getter; + +@Getter +public enum ModerationFileStatus { + ACTIVE("active"), NOT_ACTIVE("not_active"); + + private final String name; + + ModerationFileStatus(String name) { + this.name = name; + } +}