Skip to content

Commit

Permalink
refactor: 이미지 로컬로 저장하도록 수정 (#479)
Browse files Browse the repository at this point in the history
* refactor: 이미지 로컬로 저장하도록 수정

* style: 컨벤션 수정
  • Loading branch information
Choi-JJunho authored Nov 22, 2023
1 parent 7dac0bb commit ffbb49d
Show file tree
Hide file tree
Showing 16 changed files with 399 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
import com.official.pium.service.dto.PetPlantResponse;
import com.official.pium.service.dto.PetPlantUpdateRequest;
import com.official.pium.service.dto.SinglePetPlantResponse;
import java.time.LocalDate;
import java.util.List;
import java.util.NoSuchElementException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
Expand All @@ -31,13 +28,23 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.util.List;
import java.util.NoSuchElementException;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class PetPlantService {

@Value("${petPlant.image.directory}")
private String workingDirectory;
private String petPlantImageDirectory;

@Value("${local.image.web}")
private String webPath;

@Value("${dictPlant.image.directory}")
private String dictionaryPlantImageDirectory;

private final PetPlantRepository petPlantRepository;
private final DictionaryPlantRepository dictionaryPlantRepository;
Expand Down Expand Up @@ -66,7 +73,7 @@ private String saveImageIfExists(MultipartFile image, String imageDefaultUrl) {
if (image == null || image.isEmpty()) {
return imageDefaultUrl;
}
return photoManager.upload(image, workingDirectory);
return photoManager.upload(image, petPlantImageDirectory);
}

private void createHistory(PetPlant petPlant) {
Expand Down Expand Up @@ -132,8 +139,12 @@ private String updateImage(MultipartFile image, String originalImageUrl) {
if (image == null || image.isEmpty()) {
return originalImageUrl;
}
photoManager.delete(originalImageUrl, workingDirectory);
return photoManager.upload(image, workingDirectory);

if (!originalImageUrl.startsWith(webPath + dictionaryPlantImageDirectory)) {
photoManager.delete(originalImageUrl, petPlantImageDirectory);
}

return photoManager.upload(image, petPlantImageDirectory);
}

private void publishPetPlantHistories(PetPlant petPlant, PetPlantHistory previousPetPlantHistory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;
@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DictionaryPlantResponse {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.official.pium.util;

import com.official.pium.service.PhotoManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Component
public class PhotoLocalManager implements PhotoManager {

private static final String SLASH = "/";
private static final int NOT_FOUND_INDEX = -1;

@Value("${local.image.web}")
private String webPath;

@Value("${local.image.root}")
private String localPath;

@Override
public String upload(MultipartFile multipartFile, String workingDirectory) {
if (multipartFile == null || multipartFile.isEmpty()) {
throw new IllegalArgumentException("이미지 파일이 존재하지 않습니다. multipartFile: " + null);
}
return uploadPhoto(multipartFile, workingDirectory);
}

private String uploadPhoto(MultipartFile multipartFile, String workingDirectory) {
try {
String fileName = PhotoNameGenerator.of(multipartFile.getOriginalFilename());
File uploadDirectory = loadDirectory(getLocalDirectoryPath(workingDirectory));
File uploadPath = new File(uploadDirectory, fileName);
uploadFileInLocal(multipartFile, uploadPath);

return webPath + SLASH + uploadDirectory + SLASH + fileName;
} catch (Exception e) {
throw new IllegalStateException("파일 업로드를 실패했습니다.");
}
}

private String getLocalDirectoryPath(String workingDirectory) {
return localPath + SLASH + workingDirectory;
}

private File loadDirectory(String directoryLocation) {
File directory = new File(directoryLocation);
if (!directory.exists()) {
directory.mkdirs();
}
return directory;
}

private void uploadFileInLocal(MultipartFile multipartFile, File uploadPath) {
try {
multipartFile.transferTo(uploadPath);
} catch (IOException e) {
throw new IllegalStateException("파일 변환이 실패했습니다.");
}
}

@Override
public void delete(String originalImageUrl, String workingDirectory) {
String deletePath = getFileLocalPath(originalImageUrl);
File file = new File(deletePath);
deleteFile(file);
}

private String getFileLocalPath(String fullPath) {
int urlIndex = fullPath.lastIndexOf(webPath);

if (urlIndex == NOT_FOUND_INDEX) {
throw new IllegalArgumentException("잘못된 파일 경로입니다.");
}
int urlNextIndex = urlIndex + webPath.length();
return localPath + fullPath.substring(urlNextIndex);
}

private void deleteFile(File file) {
if (file.exists()) {
file.delete();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import java.io.IOException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

@Component
@RequiredArgsConstructor
public class PhotoS3Manager implements PhotoManager {

Expand Down Expand Up @@ -51,7 +49,6 @@ private String uploadPhoto(MultipartFile multipartFile, String workingDirectory)
file.delete();
return rootPath + SLASH + directory + workingDirectory + SLASH + fileName;
} catch (Exception e) {
e.printStackTrace();
throw new IllegalStateException("파일 업로드를 실패했습니다.");
}
}
Expand All @@ -72,7 +69,6 @@ private File uploadFileInLocal(MultipartFile multipartFile, File uploadPath) {
try {
multipartFile.transferTo(uploadPath);
} catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException("파일 변환이 실패했습니다.");
}
return uploadPath;
Expand Down
37 changes: 0 additions & 37 deletions backend/pium/src/main/resources/application.properties

This file was deleted.

85 changes: 85 additions & 0 deletions backend/pium/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
spring:
flyway:
enabled: false
sql:
init:
schema-locations: classpath:sql/schema.sql
data-locations: classpath:sql/data.sql
mode: always
mvc:
hiddenmethod:
filter:
enabled: true
jpa:
hibernate:
ddl-auto: validate
properties:
hibernate:
format_sql: true
show-sql: true
datasource:
username: sa
url: jdbc:h2:mem:test;MODE=MYSQL
management:
endpoint:
health:
enabled: true
endpoints:
enabled-by-default: false
fcm:
key:
path: test/
scope: https://www.googleapis.com/auth/firebase.messaging
api:
url: https://fcm.googleapis.com/v1/projects/project-id/messages:send
petPlant:
image:
directory: test
dictPlant:
image:
directory: /dict
server:
servlet:
session:
cookie:
secure: true
same-site: none
logging:
level:
org:
hibernate:
orm:
jdbc:
bind: trace
slack:
webhook-url: https://WEB_HOOK_URL.com
admin:
secondPassword: 123
password: 123
account: asdf
aws:
s3:
root: https://test.image.storage
directory: test
folder: test/
bucket: test/

local:
image:
root: src/test/resources
web: https://static.pium.life
auth:
kakao:
member-info-request-uri: https://kapi.kakao.com/v2/user/me
unlink-uri: https://kapi.kakao.com/v1/user/unlink
redirect-uri: http://localhost:8282/authorization
client-id: REST_API_KEY
token-request-uri: https://kauth.kakao.com/oauth/token
admin-id: ADMIN_KEY
registration:
image:
directory: registration
view:
image:
favicion: https://static.pium.life/prod/favicon.ico
home: https://static.pium.life/prod/home.png
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;

import java.time.LocalDateTime;
import java.util.List;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Nested;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.official.pium.config;

import org.springframework.stereotype.Component;

import java.io.File;

@Component
public class ImageCleaner {

private static final String TEST_FILE_ROOT_PATH = "src/test/resources/";

public static void cleanUp() {
deleteFolder(TEST_FILE_ROOT_PATH);
}

private static void deleteFolder(String path) {
File folder = new File(path);
if (folder.exists()) {
deleteFileRecursive(folder);
}
}

private static void deleteFileRecursive(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null) {
return;
}

for (File child : files) {
deleteFileRecursive(child);
}
}
if (file.getName().contains("application.yml")) {
return;
}
file.delete();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.official.pium.config;

import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

public class ImageCleanerExtension implements AfterEachCallback {

@Override
public void afterEach(ExtensionContext context) {
ImageCleaner.cleanUp();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.official.pium.fixture;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class FileFixture {

public static final String IMAGE_PATH = "image";
private static final byte[] IMAGE = generateMockImage();

public static byte[] generateMockImage() {
Expand Down
Loading

0 comments on commit ffbb49d

Please sign in to comment.