From 3a39cbee1181b5897ca9c7b734197e78b4d99d73 Mon Sep 17 00:00:00 2001 From: Bartha Maxime <231026@umons.ac.be> Date: Sun, 10 Mar 2024 22:23:20 +0100 Subject: [PATCH] Storage System --- .../b97fdd51-c4a7-4c13-b70c-4b91eb0b3179.png | Bin 0 -> 11586 bytes .../Clyde/EndPoints/StorageController.java | 30 +++++++ .../Clyde/EndPoints/UserController.java | 2 +- .../Clyde/Repositories/FileRepository.java | 9 ++ .../Clyde/Services/StorageService.java | 78 ++++++++++++++++++ .../herisson/Clyde/Tables/StorageFile.java | 51 ++++++++++++ .../java/ovh/herisson/Clyde/Tables/User.java | 3 +- 7 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 backend/cdn/b97fdd51-c4a7-4c13-b70c-4b91eb0b3179.png create mode 100644 backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java diff --git a/backend/cdn/b97fdd51-c4a7-4c13-b70c-4b91eb0b3179.png b/backend/cdn/b97fdd51-c4a7-4c13-b70c-4b91eb0b3179.png new file mode 100644 index 0000000000000000000000000000000000000000..0ad7d033c5618af21cd4e6c19c36845a03aafb81 GIT binary patch literal 11586 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 literal 0 HcmV?d00001 diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java new file mode 100644 index 0000000..21fabcc --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java @@ -0,0 +1,30 @@ +package ovh.herisson.Clyde.EndPoints; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import ovh.herisson.Clyde.Services.StorageService; +import org.springframework.core.io.Resource; + +@RestController +public class StorageController { + + private final StorageService storageServ; + + public StorageController(StorageService storageServ){ + this.storageServ= storageServ; + } + + + @PostMapping("/upload") + public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) { + + String path = storageServ.store(file); + + if (path == null) return new ResponseEntity<>("issue with the file storage", HttpStatus.BAD_REQUEST); + + return new ResponseEntity<>(path, HttpStatus.OK); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java index ba54926..1656d21 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java @@ -31,7 +31,7 @@ public class UserController { return new ResponseEntity<>(user, HttpStatus.OK); } - @PostMapping("/user") + @PostMapping("/user") //todo check role public ResponseEntity postUser(@RequestBody User user){ userService.save(user); return new ResponseEntity(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED); diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java new file mode 100644 index 0000000..2240c92 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java @@ -0,0 +1,9 @@ +package ovh.herisson.Clyde.Repositories; + +import org.springframework.data.repository.CrudRepository; + +import ovh.herisson.Clyde.Tables.StorageFile; + + +public interface FileRepository extends CrudRepository { +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java new file mode 100644 index 0000000..1fc9b65 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java @@ -0,0 +1,78 @@ +package ovh.herisson.Clyde.Services; + +import org.springframework.core.io.UrlResource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import ovh.herisson.Clyde.Repositories.FileRepository; +import ovh.herisson.Clyde.Tables.StorageFile; +import java.io.IOException; +import org.springframework.core.io.Resource; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Objects; +import java.util.UUID; + +@Service +public class StorageService { + + + private final Path rootLocation = Paths.get("cdn/"); + private final FileRepository fileRepo; + + public StorageService(FileRepository filerepo){ + this.fileRepo = filerepo; + } + + + public String store(MultipartFile file) { + UUID uuid = UUID.randomUUID(); + String stringUuid = uuid.toString() + "." + file.getContentType().split("/",2)[1]; + + try { + if (file.isEmpty()) { + return null; + } + + Path destinationFile = this.rootLocation.resolve(Paths.get(stringUuid)).toAbsolutePath(); + + if (!destinationFile.getParent().equals(this.rootLocation.toAbsolutePath())) { + return null;} + + Files.copy(file.getInputStream(), destinationFile,StandardCopyOption.REPLACE_EXISTING); + } + catch (IOException e) { + e.printStackTrace(); + return null; + } + + String url = this.rootLocation.resolve(Paths.get(Objects.requireNonNull(stringUuid))) + .normalize().toAbsolutePath().toString(); + System.out.println(url); + fileRepo.save(new StorageFile(file.getName(),url)); + + return url; + } + + public Path load(String filename) { + return rootLocation.resolve(filename); + } + + public Resource loadAsResource(String filename) { + try { + Path file = load(filename); + Resource resource = new UrlResource(file.toUri()); + if (resource.exists() || resource.isReadable()) { + return resource; + } + else {return null; + } + } + catch (Exception e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java new file mode 100644 index 0000000..97c1d30 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java @@ -0,0 +1,51 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + + +@Entity +public class StorageFile { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + private String url; + + public StorageFile(String name, String url){ + this.name = name; + this.url = url; + } + + public StorageFile(){} + + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java index 95467a4..0752014 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java @@ -23,7 +23,8 @@ public class User { private String profilePictureUrl; private ovh.herisson.Clyde.Tables.Role role; private String password; - public User(String lastName, String firstName, String email, String address, String country, Date birthDate, String profilePictureUrl, Role role, String password){ + public User(String lastName, String firstName, String email, String address, + String country, Date birthDate, String profilePictureUrl, Role role, String password){ this.lastName = lastName; this.firstName = firstName; this.email = email;