Files
no-copy/src/main/java/ru/soune/nocopy/controller/FileController.java
T

201 lines
7.7 KiB
Java
Raw Normal View History

2026-01-27 20:27:39 +07:00
package ru.soune.nocopy.controller;
2026-03-24 16:16:16 +07:00
import com.vrt.NoCopyFileService;
import com.vrt.fileprotection.FileProtector;
import lombok.AllArgsConstructor;
2026-01-27 20:27:39 +07:00
import lombok.extern.slf4j.Slf4j;
2026-04-20 18:16:46 +07:00
import org.springframework.core.io.InputStreamResource;
2026-01-27 20:27:39 +07:00
import org.springframework.core.io.Resource;
2026-02-21 23:21:44 +07:00
import org.springframework.http.*;
2026-01-28 23:25:16 +07:00
import org.springframework.web.bind.annotation.*;
import ru.soune.nocopy.dto.file.CheckStatus;
2026-01-27 20:27:39 +07:00
import ru.soune.nocopy.entity.file.FileEntity;
2026-01-28 18:38:43 +07:00
import ru.soune.nocopy.entity.file.ProtectionStatus;
2026-01-28 23:25:16 +07:00
import ru.soune.nocopy.entity.user.ProtectedFileCheck;
import ru.soune.nocopy.entity.user.User;
2026-01-27 20:27:39 +07:00
import ru.soune.nocopy.repository.FileEntityRepository;
2026-01-28 23:25:16 +07:00
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.file.CheckCounterService;
2026-01-27 20:27:39 +07:00
import ru.soune.nocopy.service.file.FileStorageService;
2026-02-26 00:27:31 +07:00
import ru.soune.nocopy.service.file.ImageResizeService;
import ru.soune.nocopy.service.file.ZipService;
2026-04-20 18:16:46 +07:00
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
2026-03-24 16:16:16 +07:00
import ru.soune.nocopy.util.FileUtil;
2026-02-16 18:57:45 +07:00
2026-04-20 18:16:46 +07:00
import java.io.File;
import java.io.FileInputStream;
2026-02-21 23:21:44 +07:00
import java.io.FileNotFoundException;
2026-02-16 18:57:45 +07:00
import java.net.URLEncoder;
2026-02-10 12:46:45 +07:00
import java.nio.charset.StandardCharsets;
2026-01-27 20:27:39 +07:00
import java.io.IOException;
2026-02-21 23:21:44 +07:00
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
2026-01-27 20:27:39 +07:00
@RestController
@RequestMapping("/api/files")
@Slf4j
@AllArgsConstructor
2026-01-27 20:27:39 +07:00
public class FileController {
private FileStorageService fileStorageService;
private FileEntityRepository fileRepository;
2026-01-28 23:25:16 +07:00
private CheckCounterService checkCounterService;
private UserRepository userRepository;
2026-02-26 00:27:31 +07:00
private ImageResizeService imageResizeService;
2026-02-21 23:21:44 +07:00
2026-03-24 16:16:16 +07:00
private NoCopyFileService noCopyFileService;
private FileUtil fileUtil;
private ZipService zipService;
2026-04-20 18:16:46 +07:00
private CloudStorageService cloudStorageService;
2026-01-27 20:27:39 +07:00
@GetMapping("/public/{fileId}")
2026-02-21 23:21:44 +07:00
public ResponseEntity<Resource> getPublicFile(@PathVariable String fileId) {
try {
FileEntity fileEntity = fileRepository.findById(fileId)
.orElseThrow(() -> new FileNotFoundException("Not found: " + fileId));
2026-01-27 20:27:39 +07:00
2026-02-21 23:21:44 +07:00
Path filePath = Paths.get(fileEntity.getFilePath());
if (!Files.exists(filePath)) {
log.error("Not on disk: {}", fileEntity.getFilePath());
return ResponseEntity.notFound().build();
}
2026-01-27 20:27:39 +07:00
2026-04-20 18:16:46 +07:00
File file = cloudStorageService.readFileFromStorageByPath(fileEntity.getFilePath());
if (file == null || !file.exists()) {
log.error("File not found in storage: {}", fileEntity.getFilePath());
return ResponseEntity.notFound().build();
}
2026-02-05 03:30:15 +07:00
2026-02-21 23:21:44 +07:00
MediaType mediaType = getMediaType(fileEntity);
2026-02-10 12:46:45 +07:00
2026-02-21 23:21:44 +07:00
ContentDisposition contentDisposition = ContentDisposition.inline()
.filename(fileEntity.getOriginalFileName(), StandardCharsets.UTF_8)
.build();
2026-04-20 18:16:46 +07:00
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
2026-02-21 23:21:44 +07:00
return ResponseEntity.ok()
.contentType(mediaType)
.contentLength(Files.size(filePath))
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
.header(HttpHeaders.CACHE_CONTROL, "public, max-age=3600")
.body(resource);
} catch (FileNotFoundException e) {
log.warn("Not on disk: {}", fileId);
return ResponseEntity.notFound().build();
} catch (IOException e) {
log.error("Read file exception: {}", fileId, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
private MediaType getMediaType(FileEntity fileEntity) {
try {
return MediaType.parseMediaType(fileEntity.getMimeType());
} catch (InvalidMediaTypeException e) {
String extension = fileEntity.getFileExtension().toLowerCase();
switch (extension) {
case "jpg":
case "jpeg":
return MediaType.IMAGE_JPEG;
case "png":
return MediaType.IMAGE_PNG;
case "pdf":
return MediaType.APPLICATION_PDF;
default:
return MediaType.APPLICATION_OCTET_STREAM;
}
}
2026-02-05 03:30:15 +07:00
}
2026-02-26 00:27:31 +07:00
@GetMapping("/protected/{fileId}/{type}")
2026-02-05 03:30:15 +07:00
public ResponseEntity<Resource> getProtectedFile(
2026-02-26 00:27:31 +07:00
@PathVariable String fileId, @PathVariable String type) throws IOException {
2026-02-05 03:30:15 +07:00
FileEntity fileEntity = fileRepository.findById(fileId)
.orElseThrow(() -> new RuntimeException("File not found"));
2026-01-27 20:27:39 +07:00
2026-04-20 18:16:46 +07:00
File file = cloudStorageService.readFileFromStorageByPath(fileEntity.getFilePath());
2026-02-26 00:27:31 +07:00
2026-04-20 18:16:46 +07:00
if (file == null || !file.exists()) {
log.error("File not found in storage: {}", fileEntity.getFilePath());
return ResponseEntity.notFound().build();
}
2026-01-27 20:27:39 +07:00
2026-02-05 03:30:15 +07:00
if (fileEntity.getProtectionStatus() == ProtectionStatus.NOT_PROTECTED ||
fileEntity.getProtectionStatus() == ProtectionStatus.PROCESSING) {
throw new RuntimeException("File is not protected");
}
2026-02-17 10:54:51 +07:00
String fileName = fileEntity.getOriginalFileName().replace("." +
fileEntity.getFileExtension(), "") + "_nocopy_protected" +
"." + fileEntity.getFileExtension();
2026-02-16 18:57:45 +07:00
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
.replace("+", "%20");
2026-04-20 18:16:46 +07:00
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
2026-01-27 20:27:39 +07:00
return ResponseEntity.ok()
.contentType(new MediaType(fileEntity.getMimeType(), fileEntity.getFileExtension()))
.header(HttpHeaders.CONTENT_DISPOSITION,
2026-02-16 18:57:45 +07:00
"inline; filename*=UTF-8''" + encodedFileName)
2026-01-27 20:27:39 +07:00
.body(resource);
}
2026-01-28 23:25:16 +07:00
@GetMapping("check-file/status/{userId}")
public ResponseEntity<CheckStatus> getStatus(@PathVariable Long userId) {
CheckStatus status = checkCounterService.getCurrentStatus(userId);
return ResponseEntity.ok(status);
}
@PostMapping("check-file/update-limit/{userId}/{limit}")
public ResponseEntity<ProtectedFileCheck> getStatus(@PathVariable Long userId, @PathVariable Integer limit) {
User user = userRepository.findById(userId).orElseThrow();
ProtectedFileCheck protectedFileCheck = checkCounterService.updateLimit(user, limit);
return ResponseEntity
.ok()
.body(protectedFileCheck);
}
2026-03-24 16:16:16 +07:00
@PostMapping("protect/{fileId}/{convertTo}")
public ResponseEntity<FileProtector.FileInfo> convert(@PathVariable String fileId, @PathVariable String convertTo) {
FileEntity file = fileRepository.findByFileId(fileId);
FileProtector.FileInfo fileInfo = fileUtil.createFileInfo(file, convertTo);
noCopyFileService.addFile(fileInfo);
return ResponseEntity
.ok()
.body(fileInfo);
}
@GetMapping("/download/user-passport/archive/{userId}")
public ResponseEntity<byte[]> 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();
}
}
2026-01-27 20:27:39 +07:00
}