add fileentity controller
Test Workflow / test (push) Successful in 3s

This commit is contained in:
vladp
2025-12-18 01:13:19 +07:00
parent e2747fc999
commit f3aa6324c2
15 changed files with 447 additions and 345 deletions
@@ -1,9 +1,7 @@
package ru.soune.nocopy.controller;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
@@ -19,10 +17,7 @@ import ru.soune.nocopy.dto.file.UploadProgress;
import ru.soune.nocopy.entity.file.UploadStatus;
import ru.soune.nocopy.exception.NotValidFieldException;
import ru.soune.nocopy.exception.ValidationException;
import ru.soune.nocopy.handler.FileUploadHandler;
import ru.soune.nocopy.handler.LoginRequestHandler;
import ru.soune.nocopy.handler.RegRequestHandler;
import ru.soune.nocopy.handler.RequestHandler;
import ru.soune.nocopy.handler.*;
import ru.soune.nocopy.service.file.FileUploadService;
import java.util.HashMap;
@@ -35,21 +30,10 @@ import java.util.stream.Collectors;
@RequestMapping("/api")
@RequiredArgsConstructor
public class ApiController {
private final ApplicationContext applicationContext;
private final FileUploadService fileUploadService;
private Map<Integer, RequestHandler> handlers = new HashMap<>();
private final Map<Integer, RequestHandler> handlers;
@PostConstruct
public void init() {
RegRequestHandler regHandler = applicationContext.getBean(RegRequestHandler.class);
LoginRequestHandler loginHandler = applicationContext.getBean(LoginRequestHandler.class);
FileUploadHandler fileUploadHandler = applicationContext.getBean(FileUploadHandler.class);
handlers.put(20004, fileUploadHandler);
handlers.put(20002, regHandler);
handlers.put(20001, loginHandler);
}
@PostMapping("/v{version}/data")
public ResponseEntity<?> handlePostRequest(@RequestBody BaseRequest request,
@@ -1,210 +0,0 @@
package ru.soune.nocopy.controller.file;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.soune.nocopy.dto.file.FileApiResponse;
import ru.soune.nocopy.dto.file.FileEntityResponse;
import ru.soune.nocopy.dto.file.FileListResponse;
import ru.soune.nocopy.entity.AuthToken;
import ru.soune.nocopy.exception.NotFoundAuthToken;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.service.file.FileEntityService;
@Slf4j
@RestController
@RequestMapping("/api/file-entities")
@RequiredArgsConstructor
public class FileEntityController {
private final FileEntityService fileEntityService;
private final AuthTokenRepository authTokenRepository;
/**
* Получить информацию о файле по ID
*/
@GetMapping("/{fileId}")
public ResponseEntity<FileApiResponse<FileEntityResponse>> getFileInfo(
@PathVariable String fileId,
@RequestHeader("Authorization") String tokenHeader) {
try {
Long userId = getUserIdFromToken(tokenHeader);
FileEntityResponse fileInfo = fileEntityService.getById(fileId);
if (!fileInfo.getUserId().equals(userId)) {
return ResponseEntity.status(403)
.body(FileApiResponse.error("Access denied"));
}
return ResponseEntity.ok(FileApiResponse.success(fileInfo));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error getting file info", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to get file info: " + e.getMessage()));
}
}
/**
* Получить информацию о файле по ID сессии загрузки
*/
@GetMapping("/by-session/{uploadSessionId}")
public ResponseEntity<FileApiResponse<FileEntityResponse>> getFileByUploadSession(
@PathVariable String uploadSessionId,
@RequestHeader("Authorization") String tokenHeader) {
try {
Long userId = getUserIdFromToken(tokenHeader);
FileEntityResponse fileInfo = fileEntityService.getByUploadSessionId(uploadSessionId);
if (!fileInfo.getUserId().equals(userId)) {
return ResponseEntity.status(403)
.body(FileApiResponse.error("Access denied"));
}
return ResponseEntity.ok(FileApiResponse.success(fileInfo));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error getting file by session", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to get file: " + e.getMessage()));
}
}
/**
* Получить все файлы пользователя
*/
@GetMapping("/my-files")
public ResponseEntity<FileApiResponse<FileListResponse>> getUserFiles(
@RequestHeader("Authorization") String tokenHeader,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int pageSize) {
try {
Long userId = getUserIdFromToken(tokenHeader);
FileListResponse files = fileEntityService.getUserFiles(userId, page, pageSize);
return ResponseEntity.ok(FileApiResponse.success(files));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error getting user files", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to get files: " + e.getMessage()));
}
}
/**
* Поиск файлов пользователя
*/
@GetMapping("/search")
public ResponseEntity<FileApiResponse<FileListResponse>> searchFiles(
@RequestParam String query,
@RequestHeader("Authorization") String tokenHeader,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int pageSize) {
try {
Long userId = getUserIdFromToken(tokenHeader);
FileListResponse allFiles = fileEntityService.getUserFiles(userId, 1, 1000);
var filteredFiles = allFiles.getFiles().stream()
.filter(f -> f.getOriginalFileName().toLowerCase().contains(query.toLowerCase()))
.toList();
int start = (page - 1) * pageSize;
int end = Math.min(start + pageSize, filteredFiles.size());
FileListResponse response = FileListResponse.builder()
.files(filteredFiles.subList(start, Math.min(end, filteredFiles.size())))
.totalCount(filteredFiles.size())
.totalSize(allFiles.getTotalSize())
.formattedTotalSize(allFiles.getFormattedTotalSize())
.page(page)
.pageSize(pageSize)
.build();
return ResponseEntity.ok(FileApiResponse.success(response));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error searching files", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to search files: " + e.getMessage()));
}
}
/**
* Получить общий размер файлов пользователя
*/
@GetMapping("/storage/usage")
public ResponseEntity<FileApiResponse<Long>> getStorageUsage(
@RequestHeader("Authorization") String tokenHeader) {
try {
Long userId = getUserIdFromToken(tokenHeader);
long usage = fileEntityService.getUserStorageUsed(userId);
return ResponseEntity.ok(FileApiResponse.success(usage));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error getting storage usage", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to get storage usage: " + e.getMessage()));
}
}
/**
* Пометить файл как удаленный
*/
@DeleteMapping("/{fileId}")
public ResponseEntity<FileApiResponse<Void>> deleteFile(
@PathVariable String fileId,
@RequestHeader("Authorization") String tokenHeader) {
try {
Long userId = getUserIdFromToken(tokenHeader);
FileEntityResponse fileInfo = fileEntityService.getById(fileId);
if (!fileInfo.getUserId().equals(userId)) {
return ResponseEntity.status(403)
.body(FileApiResponse.error("Access denied"));
}
fileEntityService.markAsDeleted(fileId);
return ResponseEntity.ok(FileApiResponse.success(
"File marked as deleted", null));
} catch (NotFoundAuthToken e) {
return ResponseEntity.status(401)
.body(FileApiResponse.error("Authentication required"));
} catch (Exception e) {
log.error("Error deleting file", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Failed to delete file: " + e.getMessage()));
}
}
private Long getUserIdFromToken(String tokenHeader) {
String token = tokenHeader.replace("Bearer ", "");
AuthToken authToken = authTokenRepository.findByToken(token)
.orElseThrow(() -> new NotFoundAuthToken("Token not found"));
return authToken.getUser().getId();
}
}
@@ -1,65 +0,0 @@
package ru.soune.nocopy.controller.file;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.soune.nocopy.dto.file.FileApiResponse;
import ru.soune.nocopy.dto.file.InitUploadRequest;
import ru.soune.nocopy.dto.file.UploadProgressResponse;
import ru.soune.nocopy.entity.AuthToken;
import ru.soune.nocopy.entity.file.FileType;
import ru.soune.nocopy.entity.file.FileUploadSession;
import ru.soune.nocopy.entity.file.UploadStatus;
import ru.soune.nocopy.exception.FileUploadException;
import ru.soune.nocopy.exception.NotFoundAuthToken;
import ru.soune.nocopy.exception.UploadSessionNotFoundException;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.repository.FileUploadSessionRepository;
import ru.soune.nocopy.service.file.FileUploadService;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("/api/files")
@RequiredArgsConstructor
public class FileUploadController {
private final FileUploadService fileUploadService;
@PostMapping("/chunk")
public ResponseEntity<FileApiResponse<UploadProgressResponse>> uploadChunk(
@RequestParam("uploadId") String uploadId,
@RequestParam("chunkNumber") Integer chunkNumber,
@RequestParam("chunk") MultipartFile chunk) {
log.info("Uploading chunk {} for session {}, file size: {} bytes",
chunkNumber, uploadId, chunk.getSize());
if (chunk.isEmpty()) {
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Chunk file is empty"));
}
if (uploadId == null || uploadId.isBlank()) {
return ResponseEntity.badRequest()
.body(FileApiResponse.error("Upload ID is required"));
}
try {
UploadProgressResponse progress = fileUploadService.uploadChunk(
uploadId, chunkNumber, chunk);
return ResponseEntity.ok(FileApiResponse.success(progress));
} catch (Exception e) {
log.error("Error uploading chunk", e);
return ResponseEntity.badRequest()
.body(FileApiResponse.error(e.getMessage()));
}
}
}