diff --git a/backend/pom.xml b/backend/pom.xml
index 9f2157b4..206ae451 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -151,6 +151,12 @@
com.petshop.backend.DevStackApplication
runtime
+
+
+ UPLOAD_BASE_DIR
+ ${project.basedir}/uploads
+
+
diff --git a/backend/src/main/java/com/petshop/backend/service/AvatarStorageService.java b/backend/src/main/java/com/petshop/backend/service/AvatarStorageService.java
index dff64508..2229c3d4 100644
--- a/backend/src/main/java/com/petshop/backend/service/AvatarStorageService.java
+++ b/backend/src/main/java/com/petshop/backend/service/AvatarStorageService.java
@@ -1,6 +1,7 @@
package com.petshop.backend.service;
import com.petshop.backend.entity.User;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
@@ -8,6 +9,7 @@ import org.springframework.http.MediaTypeFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
+import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -22,7 +24,15 @@ public class AvatarStorageService {
private static final String STORED_PREFIX = "/uploads/avatars/";
private static final String OWNER_ENDPOINT = "/api/v1/auth/me/avatar/file";
- private final Path avatarDirectory = Paths.get("uploads", "avatars").toAbsolutePath().normalize();
+ @Value("${app.upload.base-dir:uploads}")
+ private String uploadBaseDir;
+
+ private Path avatarDirectory;
+
+ @PostConstruct
+ private void init() {
+ avatarDirectory = Paths.get(uploadBaseDir, "avatars").toAbsolutePath().normalize();
+ }
public String storeAvatar(MultipartFile file) throws IOException {
Files.createDirectories(avatarDirectory);
@@ -101,7 +111,7 @@ public class AvatarStorageService {
}
String extension = originalFilename.substring(extensionIndex).toLowerCase(Locale.ROOT);
return switch (extension) {
- case ".jpg", ".jpeg", ".png", ".gif" -> extension;
+ case ".jpg", ".jpeg", ".png", ".gif", ".webp" -> extension;
default -> ".jpg";
};
}
diff --git a/backend/src/main/java/com/petshop/backend/service/CatalogImageStorageService.java b/backend/src/main/java/com/petshop/backend/service/CatalogImageStorageService.java
index 34a92ff0..1068e094 100644
--- a/backend/src/main/java/com/petshop/backend/service/CatalogImageStorageService.java
+++ b/backend/src/main/java/com/petshop/backend/service/CatalogImageStorageService.java
@@ -1,5 +1,6 @@
package com.petshop.backend.service;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
@@ -21,20 +22,31 @@ public class CatalogImageStorageService {
private static final String PET_PREFIX = "/uploads/pets/";
private static final String PRODUCT_PREFIX = "/uploads/products/";
+ @Value("${app.upload.base-dir:uploads}")
+ private String uploadBaseDir;
+
public String storePetImage(MultipartFile file) throws IOException {
- return storeImage(file, Paths.get("uploads", "pets").toAbsolutePath().normalize(), PET_PREFIX);
+ return storeImage(file, Paths.get(uploadBaseDir, "pets").toAbsolutePath().normalize(), PET_PREFIX);
}
public String storeProductImage(MultipartFile file) throws IOException {
- return storeImage(file, Paths.get("uploads", "products").toAbsolutePath().normalize(), PRODUCT_PREFIX);
+ return storeImage(file, Paths.get(uploadBaseDir, "products").toAbsolutePath().normalize(), PRODUCT_PREFIX);
}
public Resource loadPetImage(String storedPath) {
- return new PathResource(resolveStoredPath(storedPath, Paths.get("uploads", "pets").toAbsolutePath().normalize(), PET_PREFIX));
+ Resource resource = new PathResource(resolveStoredPath(storedPath, Paths.get(uploadBaseDir, "pets").toAbsolutePath().normalize(), PET_PREFIX));
+ if (!resource.exists()) {
+ throw new IllegalArgumentException("Image file was not found");
+ }
+ return resource;
}
public Resource loadProductImage(String storedPath) {
- return new PathResource(resolveStoredPath(storedPath, Paths.get("uploads", "products").toAbsolutePath().normalize(), PRODUCT_PREFIX));
+ Resource resource = new PathResource(resolveStoredPath(storedPath, Paths.get(uploadBaseDir, "products").toAbsolutePath().normalize(), PRODUCT_PREFIX));
+ if (!resource.exists()) {
+ throw new IllegalArgumentException("Image file was not found");
+ }
+ return resource;
}
public MediaType resolveMediaType(Resource resource) {
@@ -42,11 +54,11 @@ public class CatalogImageStorageService {
}
public void deletePetImage(String storedPath) throws IOException {
- deleteImage(storedPath, Paths.get("uploads", "pets").toAbsolutePath().normalize(), PET_PREFIX);
+ deleteImage(storedPath, Paths.get(uploadBaseDir, "pets").toAbsolutePath().normalize(), PET_PREFIX);
}
public void deleteProductImage(String storedPath) throws IOException {
- deleteImage(storedPath, Paths.get("uploads", "products").toAbsolutePath().normalize(), PRODUCT_PREFIX);
+ deleteImage(storedPath, Paths.get(uploadBaseDir, "products").toAbsolutePath().normalize(), PRODUCT_PREFIX);
}
private String storeImage(MultipartFile file, Path directory, String prefix) throws IOException {
@@ -90,7 +102,7 @@ public class CatalogImageStorageService {
}
String extension = originalFilename.substring(extensionIndex).toLowerCase(Locale.ROOT);
return switch (extension) {
- case ".jpg", ".jpeg", ".png", ".gif" -> extension;
+ case ".jpg", ".jpeg", ".png", ".gif", ".webp" -> extension;
default -> ".jpg";
};
}
diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml
index d16835fb..e3c3e0df 100644
--- a/backend/src/main/resources/application.yml
+++ b/backend/src/main/resources/application.yml
@@ -47,6 +47,10 @@ springdoc:
swagger-ui:
path: /swagger-ui
+app:
+ upload:
+ base-dir: ${UPLOAD_BASE_DIR:uploads}
+
jwt:
secret: ${JWT_SECRET}
expiration: ${JWT_EXPIRATION:86400000}