From 6b5dded7f8cdc03d89ecc4bb374d7757218a807a Mon Sep 17 00:00:00 2001 From: Andrii Solianyk Date: Thu, 24 Apr 2025 07:34:53 +0200 Subject: [PATCH] WIP for images --- Dockerfile | 6 +- compose.yaml | 7 +- .../ArtisanConnectBackendApplication.java | 14 ++++ .../controller/NoticeController.java | 80 +++++++++++++------ .../service/ImageService.java | 38 +++++++++ .../service/NoticeService.java | 9 +-- 6 files changed, 119 insertions(+), 35 deletions(-) create mode 100644 src/main/java/_11/asktpk/artisanconnectbackend/service/ImageService.java diff --git a/Dockerfile b/Dockerfile index d0e4337..7af4dfd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM openjdk:21 -COPY target/ArtisanConnectBackend-0.0.1-SNAPSHOT.jar app.jar +WORKDIR /app -ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file +COPY target/ArtisanConnectBackend-0.0.1-SNAPSHOT.jar app/artisan.jar + +ENTRYPOINT ["java","-jar","app/artisan.jar"] \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index 7703ee1..bc63629 100644 --- a/compose.yaml +++ b/compose.yaml @@ -2,10 +2,13 @@ services: app: container_name: artisan build: . - networks: - - artisan_network depends_on: - db + networks: + - artisan_network + ports: + - '8085:8080' + db: container_name: db diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/ArtisanConnectBackendApplication.java b/src/main/java/_11/asktpk/artisanconnectbackend/ArtisanConnectBackendApplication.java index b3e3b0d..ce783a5 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/ArtisanConnectBackendApplication.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/ArtisanConnectBackendApplication.java @@ -1,13 +1,27 @@ package _11.asktpk.artisanconnectbackend; +import jakarta.annotation.PostConstruct; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.core.env.Environment; @SpringBootApplication public class ArtisanConnectBackendApplication { + private final Environment environment; + + public ArtisanConnectBackendApplication(Environment environment) { + this.environment = environment; + } + public static void main(String[] args) { SpringApplication.run(ArtisanConnectBackendApplication.class, args); } + @PostConstruct + public void logDataSourceUrl() { + System.out.println("Datasource URL: " + environment.getProperty("spring.datasource.url")); + } } + + diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java index d05a339..34a0d99 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/NoticeController.java @@ -1,14 +1,17 @@ package _11.asktpk.artisanconnectbackend.controller; import _11.asktpk.artisanconnectbackend.service.ClientService; +import _11.asktpk.artisanconnectbackend.service.ImageService; import _11.asktpk.artisanconnectbackend.service.NoticeService; import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; import jakarta.persistence.EntityNotFoundException; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -20,10 +23,12 @@ import java.util.List; public class NoticeController { private final NoticeService noticeService; private final ClientService clientService; + private final ImageService imageService; - public NoticeController(NoticeService noticeService, ClientService clientService) { + public NoticeController(NoticeService noticeService, ClientService clientService, ImageService imageService) { this.noticeService = noticeService; this.clientService = clientService; + this.imageService = imageService; } @GetMapping("/get/all") @@ -110,12 +115,16 @@ public class NoticeController { @PostMapping("/upload/{id}") public ResponseEntity uploadImage(@PathVariable("id") Long id, @RequestParam("file") MultipartFile file) { + if (file.isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Nie przesłano pliku."); + } + if (!noticeService.noticeExists(id)) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Nie znaleziono ogłoszenia o ID: " + id); } try { - String filePath = noticeService.saveImage(id, file); + String filePath = noticeService.saveImage("./app/images/notices/", id, file); return ResponseEntity.ok("Zdjęcie zapisane pod ścieżką: " + filePath); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Błąd podczas zapisywania zdjęcia: " + e.getMessage()); @@ -123,37 +132,56 @@ public class NoticeController { } - @GetMapping("/images/{id}") - public ResponseEntity> getAllImages(@PathVariable("id") Long id) { + @GetMapping("/images/{noticeId}/{imageIndex}") + public ResponseEntity getImage(@PathVariable Long noticeId, @PathVariable Integer imageIndex) { try { - Path directoryPath = Paths.get("src/main/resources/static/images/notices/" + id); - if (!Files.exists(directoryPath) || !Files.isDirectory(directoryPath)) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + if (!noticeService.noticeExists(noticeId)) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } - List imagePaths = new ArrayList<>(); - Files.list(directoryPath).forEach(file -> { - if (Files.isRegularFile(file) && Files.isReadable(file)) { - imagePaths.add(file.toString()); - } - }); + NoticeDTO notice = noticeService.getNoticeById(noticeId); + List imagePaths = notice.getImages(); - if (imagePaths.isEmpty()) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + if (imagePaths == null || imagePaths.isEmpty() || imageIndex >= imagePaths.size() || imageIndex < 0) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } - return ResponseEntity.ok(imagePaths); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + String imagePath = imagePaths.get(imageIndex); + byte[] imageBytes = imageService.getImageBytes(imagePath); + MediaType mediaType = imageService.getMediaTypeForImage(imagePath); + + return ResponseEntity + .ok() + .contentType(mediaType) + .body(imageBytes); + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } -// @GetMapping("/check/{id}") -// public ResponseEntity checkNotice(@PathVariable("id") long id) { -// if (noticeService.noticeExists(id)) { -// return ResponseEntity.ok("Ogłoszenie o ID " + id + " istnieje."); -// } else { -// return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Nie znaleziono ogłoszenia o ID: " + id); -// } -// } + @GetMapping("/images/{id}") + public ResponseEntity> getNoticeImageUrls(@PathVariable("id") Long id) { + try { + if (!noticeService.noticeExists(id)) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + + NoticeDTO notice = noticeService.getNoticeById(id); + List imagePaths = notice.getImages(); + + if (imagePaths == null || imagePaths.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + + // Zamiast przesyłać bajty, zwracamy listę URL-i do obrazów + List imageUrls = new ArrayList<>(); + for (int i = 0; i < imagePaths.size(); i++) { + imageUrls.add("/api/v1/notices/images/" + id + "/" + i); + } + + return ResponseEntity.ok(imageUrls); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/ImageService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/ImageService.java new file mode 100644 index 0000000..976e6c0 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/ImageService.java @@ -0,0 +1,38 @@ +package _11.asktpk.artisanconnectbackend.service; + +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Service +public class ImageService { + + public byte[] getImageBytes(String imagePath) throws IOException { + Path path = Paths.get(imagePath); + return Files.readAllBytes(path); + } + + public Resource getImageAsResource(String imagePath) throws IOException { + Path path = Paths.get(imagePath); + Resource resource = new UrlResource(path.toUri()); + + if(resource.exists() && resource.isReadable()) { + return resource; + } else { + throw new IOException("Nie można odczytać obrazu: " + imagePath); + } + } + + public MediaType getMediaTypeForImage(String imagePath) { + return MediaTypeFactory + .getMediaType(imagePath) + .orElse(MediaType.APPLICATION_OCTET_STREAM); + } +} \ No newline at end of file diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java index 7f2b9ff..adb3d14 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/NoticeService.java @@ -113,8 +113,8 @@ public class NoticeService { } } - public String saveImage(Long noticeId, MultipartFile file) throws IOException { - String uploadDir = "src/main/resources/static/images/notices/" + noticeId; + public String saveImage(String uploadFolder, Long noticeId, MultipartFile file) throws IOException { + String uploadDir = uploadFolder + noticeId; Path uploadPath = Paths.get(uploadDir); if (!Files.exists(uploadPath)) { @@ -141,12 +141,11 @@ public class NoticeService { .orElse(0); fileName = baseName + (maxNumber + 1) + extension; + } else { + throw new IOException("Nie można znaleźć nazwy pliku"); } //koniec szukania nazwy pliku - if(fileName == null) { - throw new IOException("Nie można znaleźć nazwy pliku"); - } Path filePath = uploadPath.resolve(fileName); Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);