From b6519b7e1abbc554110153fe9fb48c11d910e1c9 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Thu, 7 Apr 2022 23:00:48 +0900 Subject: [PATCH 1/8] feat: add s3 upload pipeline --- backend/.gitignore | 2 + backend/build.gradle | 1 + .../backend/aws/component/S3Uploader.java | 75 +++++++++++++++++++ .../backend/aws/config/AmazonS3Config.java | 31 ++++++++ .../backend/aws/controller/S3Controller.java | 24 ++++++ .../resources/application-aws.yml.template | 8 ++ .../application-credentials.yml.template | 5 ++ backend/src/main/resources/application.yml | 4 + 8 files changed, 150 insertions(+) create mode 100644 backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java create mode 100644 backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java create mode 100644 backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java create mode 100644 backend/src/main/resources/application-aws.yml.template create mode 100644 backend/src/main/resources/application-credentials.yml.template diff --git a/backend/.gitignore b/backend/.gitignore index 54d95d4..2a17aab 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -60,3 +60,5 @@ out/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +/src/main/resources/application-aws.yml +/src/main/resources/application-credentials.yml diff --git a/backend/build.gradle b/backend/build.gradle index 328f8c8..b50891b 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-websocket' implementation 'org.flywaydb:flyway-core' implementation 'org.springframework.kafka:spring-kafka' + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'io.micrometer:micrometer-registry-prometheus' diff --git a/backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java b/backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java new file mode 100644 index 0000000..93662cf --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java @@ -0,0 +1,75 @@ +package com.hjjang.backend.aws.component; + +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.PutObjectRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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.FileOutputStream; +import java.io.IOException; +import java.util.Optional; +import java.util.UUID; + +@Slf4j +@RequiredArgsConstructor +@Component +public class S3Uploader { + + private final AmazonS3Client amazonS3Client; + + @Value("${cloud.aws.s3.bucket}") + public String bucket; // S3 버킷 이름 + + public String upload(MultipartFile multipartFile, String dirName) throws IOException { + File uploadFile = + convert(multipartFile) // 파일 변환할 수 없으면 에러 + .orElseThrow( + () -> new IllegalArgumentException("error: MultipartFile -> File convert fail")); + + return upload(uploadFile, dirName); + } + + // S3로 파일 업로드하기 + private String upload(File uploadFile, String dirName) { + String fileName = dirName + "/" + UUID.randomUUID() + uploadFile.getName(); // S3에 저장된 파일 이름 + String uploadImageUrl = putS3(uploadFile, fileName); // s3로 업로드 + removeNewFile(uploadFile); + return uploadImageUrl; + } + + // S3로 업로드 + private String putS3(File uploadFile, String fileName) { + amazonS3Client.putObject( + new PutObjectRequest(bucket, fileName, uploadFile) + .withCannedAcl(CannedAccessControlList.PublicRead)); + return amazonS3Client.getUrl(bucket, fileName).toString(); + } + + // 로컬에 저장된 이미지 지우기 + private void removeNewFile(File targetFile) { + if (targetFile.delete()) { + log.info("File delete success"); + return; + } + log.info("File delete fail"); + } + + // 로컬에 파일 업로드 하기 + private Optional convert(MultipartFile file) throws IOException { + File convertFile = new File(System.getProperty("user.dir") + "/" + file.getOriginalFilename()); + if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) + try (FileOutputStream fos = + new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함 + fos.write(file.getBytes()); + } + return Optional.of(convertFile); + } + + return Optional.empty(); + } +} diff --git a/backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java b/backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java new file mode 100644 index 0000000..65448ee --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java @@ -0,0 +1,31 @@ +package com.hjjang.backend.aws.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AmazonS3Config { + + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCreds)) + .build(); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java b/backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java new file mode 100644 index 0000000..d478047 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java @@ -0,0 +1,24 @@ +package com.hjjang.backend.aws.controller; + +import com.hjjang.backend.aws.component.S3Uploader; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@RequiredArgsConstructor +@RestController +public class S3Controller { + + private final S3Uploader s3Uploader; + + //TODO: 이미지가 일정 용량 이상일 경우 업로드가 안되는데, 그 과정에서 이미지가 로컬에 저장은 되고 방치됌 -> 동일 파일 이름으로 이미지 업로드시 오류 유발 + @PostMapping("/images") + public String upload(@RequestParam("images") MultipartFile multipartFile) throws IOException { + s3Uploader.upload(multipartFile, "static"); + return "test"; + } +} diff --git a/backend/src/main/resources/application-aws.yml.template b/backend/src/main/resources/application-aws.yml.template new file mode 100644 index 0000000..e25fa48 --- /dev/null +++ b/backend/src/main/resources/application-aws.yml.template @@ -0,0 +1,8 @@ +cloud: + aws: + s3: + bucket: + region: + static: ap-northeast-2 + stack: + auto: false \ No newline at end of file diff --git a/backend/src/main/resources/application-credentials.yml.template b/backend/src/main/resources/application-credentials.yml.template new file mode 100644 index 0000000..7e67bb1 --- /dev/null +++ b/backend/src/main/resources/application-credentials.yml.template @@ -0,0 +1,5 @@ +cloud: + aws: + credentials: + accessKey: + secretKey: \ No newline at end of file diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index a76eea0..94ecc3c 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -1,6 +1,10 @@ spring: application: name: "backend" + profiles: + include: + - aws + - credentials datasource: driver-class-name: "com.mysql.cj.jdbc.Driver" url: "jdbc:mysql://localhost:3306/test_db?useSSL=false&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&autoReconnect=true&createDatabaseIfNotExist=true" From 976a3ecb538a8b39004bb7f1d9fca3c31aace358 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sat, 30 Apr 2022 11:31:00 +0900 Subject: [PATCH 2/8] chore : move s3 package --- .../backend/{ => infra}/aws/component/S3Uploader.java | 2 +- .../backend/{ => infra}/aws/config/AmazonS3Config.java | 2 +- .../backend/{ => infra}/aws/controller/S3Controller.java | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) rename backend/src/main/java/com/hjjang/backend/{ => infra}/aws/component/S3Uploader.java (98%) rename backend/src/main/java/com/hjjang/backend/{ => infra}/aws/config/AmazonS3Config.java (95%) rename backend/src/main/java/com/hjjang/backend/{ => infra}/aws/controller/S3Controller.java (79%) diff --git a/backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java b/backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java similarity index 98% rename from backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java rename to backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java index 93662cf..edfe046 100644 --- a/backend/src/main/java/com/hjjang/backend/aws/component/S3Uploader.java +++ b/backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.aws.component; +package com.hjjang.backend.infra.aws.component; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.CannedAccessControlList; diff --git a/backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java b/backend/src/main/java/com/hjjang/backend/infra/aws/config/AmazonS3Config.java similarity index 95% rename from backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java rename to backend/src/main/java/com/hjjang/backend/infra/aws/config/AmazonS3Config.java index 65448ee..f866d59 100644 --- a/backend/src/main/java/com/hjjang/backend/aws/config/AmazonS3Config.java +++ b/backend/src/main/java/com/hjjang/backend/infra/aws/config/AmazonS3Config.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.aws.config; +package com.hjjang.backend.infra.aws.config; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; diff --git a/backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java b/backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java similarity index 79% rename from backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java rename to backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java index d478047..cd8b1f5 100644 --- a/backend/src/main/java/com/hjjang/backend/aws/controller/S3Controller.java +++ b/backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java @@ -1,8 +1,9 @@ -package com.hjjang.backend.aws.controller; +package com.hjjang.backend.infra.aws.controller; -import com.hjjang.backend.aws.component.S3Uploader; +import com.hjjang.backend.infra.aws.component.S3Uploader; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -10,13 +11,14 @@ import java.io.IOException; @RequiredArgsConstructor +@RequestMapping("/api/images") @RestController public class S3Controller { private final S3Uploader s3Uploader; //TODO: 이미지가 일정 용량 이상일 경우 업로드가 안되는데, 그 과정에서 이미지가 로컬에 저장은 되고 방치됌 -> 동일 파일 이름으로 이미지 업로드시 오류 유발 - @PostMapping("/images") + @PostMapping public String upload(@RequestParam("images") MultipartFile multipartFile) throws IOException { s3Uploader.upload(multipartFile, "static"); return "test"; From a52af52aab9fdd6e7a332743cc5acd548f5afe9b Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sat, 30 Apr 2022 15:39:30 +0900 Subject: [PATCH 3/8] debug : s3 not uploaded problem --- .../image/controller/ImageController.java | 61 +++++++++++++++++++ .../image/domain/entity/Image.java | 2 +- .../domain/repository/ImageRepository.java | 4 +- .../{infra => domain}/image/dto/ImageDto.java | 4 +- .../domain/image/dto/ImagePathResponse.java | 20 ++++++ .../exception/ImageNotFoundException.java | 2 +- .../image/service/ImageService.java | 7 +-- .../image/service/LocalImageService.java} | 25 +++----- .../domain/image/service/S3ImageService.java | 44 +++++++++++++ .../domain/post/domain/entity/Post.java | 2 - .../infra/aws/controller/S3Controller.java | 26 -------- .../image/controller/ImageController.java | 47 -------------- .../infra/image/dto/ImageResponse.java | 20 ------ .../component/ImageUploader.java | 2 +- .../component/LocalUploader.java | 7 +-- .../infra/uploader/component/Path.java | 14 +++++ .../component/S3Uploader.java | 26 +++++--- 17 files changed, 178 insertions(+), 135 deletions(-) create mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java rename backend/src/main/java/com/hjjang/backend/{infra => domain}/image/domain/entity/Image.java (89%) rename backend/src/main/java/com/hjjang/backend/{infra => domain}/image/domain/repository/ImageRepository.java (53%) rename backend/src/main/java/com/hjjang/backend/{infra => domain}/image/dto/ImageDto.java (78%) create mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/dto/ImagePathResponse.java rename backend/src/main/java/com/hjjang/backend/{infra => domain}/image/exception/ImageNotFoundException.java (86%) rename backend/src/main/java/com/hjjang/backend/{infra => domain}/image/service/ImageService.java (53%) rename backend/src/main/java/com/hjjang/backend/{infra/image/service/ImageServiceImpl.java => domain/image/service/LocalImageService.java} (51%) create mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java delete mode 100644 backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java delete mode 100644 backend/src/main/java/com/hjjang/backend/infra/image/controller/ImageController.java delete mode 100644 backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageResponse.java rename backend/src/main/java/com/hjjang/backend/infra/{image => uploader}/component/ImageUploader.java (87%) rename backend/src/main/java/com/hjjang/backend/infra/{image => uploader}/component/LocalUploader.java (84%) create mode 100644 backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java rename backend/src/main/java/com/hjjang/backend/infra/{aws => uploader}/component/S3Uploader.java (72%) diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java new file mode 100644 index 0000000..fee4454 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java @@ -0,0 +1,61 @@ +package com.hjjang.backend.domain.image.controller; + +import com.hjjang.backend.domain.image.domain.entity.Image; +import com.hjjang.backend.domain.image.dto.ImagePathResponse; +import com.hjjang.backend.domain.image.service.LocalImageService; +import com.hjjang.backend.domain.image.service.S3ImageService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static com.hjjang.backend.global.util.HttpStatusResponseEntity.RESPONSE_OK; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/images") +public class ImageController { + + private final LocalImageService imageService; + + @GetMapping() + public ResponseEntity> findAllImage() { + return ResponseEntity.ok(imageService + .findAll() + .stream() + .map(ImagePathResponse::of) + .collect(Collectors.toList()) + ); + } + + @PostMapping() + public ResponseEntity uploadImage(@RequestParam("images") MultipartFile multipartFile) throws IOException { + return ResponseEntity.ok(ImagePathResponse + .of(imageService + .uploadNewImage(multipartFile) + ) + ); + } + + @GetMapping("/{imageId}") + public ResponseEntity findImage(@PathVariable Long imageId) { + return ResponseEntity.ok(ImagePathResponse + .of(imageService + .findImageById(imageId) + ) + ); + } + + @DeleteMapping("/{imageId}") + public ResponseEntity deleteIMage(@PathVariable Long imageId) { + Image image = imageService.findImageById(imageId); + imageService.removeImage(image); + + return RESPONSE_OK; + } +} diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/domain/entity/Image.java b/backend/src/main/java/com/hjjang/backend/domain/image/domain/entity/Image.java similarity index 89% rename from backend/src/main/java/com/hjjang/backend/infra/image/domain/entity/Image.java rename to backend/src/main/java/com/hjjang/backend/domain/image/domain/entity/Image.java index cbd9e07..9353979 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/domain/entity/Image.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/domain/entity/Image.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.image.domain.entity; +package com.hjjang.backend.domain.image.domain.entity; import lombok.*; diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/domain/repository/ImageRepository.java b/backend/src/main/java/com/hjjang/backend/domain/image/domain/repository/ImageRepository.java similarity index 53% rename from backend/src/main/java/com/hjjang/backend/infra/image/domain/repository/ImageRepository.java rename to backend/src/main/java/com/hjjang/backend/domain/image/domain/repository/ImageRepository.java index a3fb42e..396cc23 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/domain/repository/ImageRepository.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/domain/repository/ImageRepository.java @@ -1,6 +1,6 @@ -package com.hjjang.backend.infra.image.domain.repository; +package com.hjjang.backend.domain.image.domain.repository; -import com.hjjang.backend.infra.image.domain.entity.Image; +import com.hjjang.backend.domain.image.domain.entity.Image; import org.springframework.data.jpa.repository.JpaRepository; public interface ImageRepository extends JpaRepository { diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageDto.java b/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java similarity index 78% rename from backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageDto.java rename to backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java index 5caad3a..d0808e4 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageDto.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java @@ -1,7 +1,7 @@ -package com.hjjang.backend.infra.image.dto; +package com.hjjang.backend.domain.image.dto; -import com.hjjang.backend.infra.image.domain.entity.Image; +import com.hjjang.backend.domain.image.domain.entity.Image; import lombok.*; import javax.validation.constraints.NotEmpty; diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImagePathResponse.java b/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImagePathResponse.java new file mode 100644 index 0000000..68c723b --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImagePathResponse.java @@ -0,0 +1,20 @@ +package com.hjjang.backend.domain.image.dto; + +import com.hjjang.backend.domain.image.domain.entity.Image; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class ImagePathResponse { + + private Long id; + private String path; + + public static ImagePathResponse of(Image image) { + return ImagePathResponse.builder() + .id(image.getId()) + .path(image.getPath()) + .build(); + } +} diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/exception/ImageNotFoundException.java b/backend/src/main/java/com/hjjang/backend/domain/image/exception/ImageNotFoundException.java similarity index 86% rename from backend/src/main/java/com/hjjang/backend/infra/image/exception/ImageNotFoundException.java rename to backend/src/main/java/com/hjjang/backend/domain/image/exception/ImageNotFoundException.java index 6b169c0..70dcd99 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/exception/ImageNotFoundException.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/exception/ImageNotFoundException.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.image.exception; +package com.hjjang.backend.domain.image.exception; public class ImageNotFoundException extends RuntimeException { diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/service/ImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java similarity index 53% rename from backend/src/main/java/com/hjjang/backend/infra/image/service/ImageService.java rename to backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java index 4313d65..58a78aa 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/service/ImageService.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java @@ -1,6 +1,6 @@ -package com.hjjang.backend.infra.image.service; +package com.hjjang.backend.domain.image.service; -import com.hjjang.backend.infra.image.domain.entity.Image; +import com.hjjang.backend.domain.image.domain.entity.Image; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -12,9 +12,8 @@ public interface ImageService { Image findImageById(Long imageId); - void uploadNewImage(MultipartFile multipartFile) throws IOException; + Image uploadNewImage(MultipartFile multipartFile) throws IOException; void removeImage(Image image); - boolean isImageInPath(Image image); } diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/service/ImageServiceImpl.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java similarity index 51% rename from backend/src/main/java/com/hjjang/backend/infra/image/service/ImageServiceImpl.java rename to backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java index 243a11b..a732372 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/service/ImageServiceImpl.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java @@ -1,10 +1,10 @@ -package com.hjjang.backend.infra.image.service; +package com.hjjang.backend.domain.image.service; -import com.hjjang.backend.infra.image.component.ImageUploader; -import com.hjjang.backend.infra.image.domain.entity.Image; -import com.hjjang.backend.infra.image.domain.repository.ImageRepository; -import com.hjjang.backend.infra.image.dto.ImageDto; -import com.hjjang.backend.infra.image.exception.ImageNotFoundException; +import com.hjjang.backend.domain.image.domain.repository.ImageRepository; +import com.hjjang.backend.domain.image.dto.ImageDto; +import com.hjjang.backend.domain.image.domain.entity.Image; +import com.hjjang.backend.domain.image.exception.ImageNotFoundException; +import com.hjjang.backend.infra.uploader.component.LocalUploader; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -16,9 +16,9 @@ @Service @RequiredArgsConstructor @Transactional -public class ImageServiceImpl implements ImageService{ +public class LocalImageService implements ImageService{ private final ImageRepository imageRepository; - private final ImageUploader imageUploader; + private final LocalUploader imageUploader; @Override public List findAll() { @@ -31,9 +31,9 @@ public Image findImageById(Long imageId) { } @Override - public void uploadNewImage(MultipartFile multipartFile) throws IOException { + public Image uploadNewImage(MultipartFile multipartFile) throws IOException { ImageDto imageDto = new ImageDto(imageUploader.upload(multipartFile)); - imageRepository.save(imageDto.toEntity()); + return imageRepository.save(imageDto.toEntity()); } @Override @@ -42,9 +42,4 @@ public void removeImage(Image image) { imageRepository.save(image); } - @Override - public boolean isImageInPath(Image image) { - //TODO: 이미지가 경로에 존재하는지 확인하는 코드 작성 - return false; - } } diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java new file mode 100644 index 0000000..a77607f --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java @@ -0,0 +1,44 @@ +package com.hjjang.backend.domain.image.service; + +import com.hjjang.backend.domain.image.domain.entity.Image; +import com.hjjang.backend.domain.image.domain.repository.ImageRepository; +import com.hjjang.backend.domain.image.exception.ImageNotFoundException; +import com.hjjang.backend.infra.uploader.component.S3Uploader; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.transaction.Transactional; +import java.io.IOException; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional +public class S3ImageService implements ImageService { + private final ImageRepository imageRepository; + private final S3Uploader imageUploader; + + @Override + public List findAll() { + return imageRepository.findAll(); + } + + @Override + public Image findImageById(Long imageId) { + return imageRepository.findById(imageId).orElseThrow(ImageNotFoundException::new); + } + + @Override + public Image uploadNewImage(MultipartFile multipartFile) throws IOException { + return imageRepository.save( + new Image(imageUploader.upload(multipartFile)) + ); + } + + @Override + public void removeImage(Image image) { + image.removeImage(); + imageRepository.save(image); + } +} diff --git a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java index 616e4f8..ef5553b 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java +++ b/backend/src/main/java/com/hjjang/backend/domain/post/domain/entity/Post.java @@ -1,7 +1,5 @@ package com.hjjang.backend.domain.post.domain.entity; -import com.hjjang.backend.domain.user.entity.User; -import com.hjjang.backend.infra.image.domain.entity.Image; import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicInsert; diff --git a/backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java b/backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java deleted file mode 100644 index cd8b1f5..0000000 --- a/backend/src/main/java/com/hjjang/backend/infra/aws/controller/S3Controller.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.hjjang.backend.infra.aws.controller; - -import com.hjjang.backend.infra.aws.component.S3Uploader; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; - -@RequiredArgsConstructor -@RequestMapping("/api/images") -@RestController -public class S3Controller { - - private final S3Uploader s3Uploader; - - //TODO: 이미지가 일정 용량 이상일 경우 업로드가 안되는데, 그 과정에서 이미지가 로컬에 저장은 되고 방치됌 -> 동일 파일 이름으로 이미지 업로드시 오류 유발 - @PostMapping - public String upload(@RequestParam("images") MultipartFile multipartFile) throws IOException { - s3Uploader.upload(multipartFile, "static"); - return "test"; - } -} diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/controller/ImageController.java b/backend/src/main/java/com/hjjang/backend/infra/image/controller/ImageController.java deleted file mode 100644 index f920983..0000000 --- a/backend/src/main/java/com/hjjang/backend/infra/image/controller/ImageController.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.hjjang.backend.infra.image.controller; - -import com.hjjang.backend.infra.image.domain.entity.Image; -import com.hjjang.backend.infra.image.dto.ImageResponse; -import com.hjjang.backend.infra.image.service.ImageService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.util.List; - -import static com.hjjang.backend.global.util.HttpStatusResponseEntity.RESPONSE_OK; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/images") -public class ImageController { - - private final ImageService imageService; - - @GetMapping() - public List findAllImage() { - return imageService.findAll(); - } - - @PostMapping() - public ResponseEntity uploadImage(@RequestParam("images") MultipartFile multipartFile) throws IOException { - imageService.uploadNewImage(multipartFile); - return RESPONSE_OK; - } - - @GetMapping("/{imageId}") - public ResponseEntity findImage(@PathVariable Long imageId) { - return ResponseEntity.ok(ImageResponse.of(imageService.findImageById(imageId))); - } - - @DeleteMapping("/{imageId}") - public ResponseEntity deleteIMage(@PathVariable Long imageId) { - Image image = imageService.findImageById(imageId); - imageService.removeImage(image); - - return RESPONSE_OK; - } -} diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageResponse.java b/backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageResponse.java deleted file mode 100644 index 58e613a..0000000 --- a/backend/src/main/java/com/hjjang/backend/infra/image/dto/ImageResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.hjjang.backend.infra.image.dto; - -import com.hjjang.backend.infra.image.domain.entity.Image; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class ImageResponse { - - private Long id; - private String path; - - public static ImageResponse of(Image image) { - return ImageResponse.builder() - .id(image.getId()) - .path(image.getPath()) - .build(); - } -} diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/component/ImageUploader.java b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java similarity index 87% rename from backend/src/main/java/com/hjjang/backend/infra/image/component/ImageUploader.java rename to backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java index 08fcce5..2588416 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/component/ImageUploader.java +++ b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.image.component; +package com.hjjang.backend.infra.uploader.component; import org.springframework.web.multipart.MultipartFile; diff --git a/backend/src/main/java/com/hjjang/backend/infra/image/component/LocalUploader.java b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java similarity index 84% rename from backend/src/main/java/com/hjjang/backend/infra/image/component/LocalUploader.java rename to backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java index f0d96d7..1374456 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/image/component/LocalUploader.java +++ b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.image.component; +package com.hjjang.backend.infra.uploader.component; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -27,13 +27,13 @@ public String upload(MultipartFile multipartFile) throws IOException { @Override public String changeFileName(MultipartFile uploadFile) { - return UUID.randomUUID() + uploadFile.getOriginalFilename(); // 저장될 파일 이름 변환 + return UUID.randomUUID() + ".png"; // 저장될 파일 이름 변환 } // 로컬에 파일 업로드 하기 @Override public Optional localUpload(MultipartFile file) throws IOException { - File convertFile = new File(System.getProperty("user.dir") + "/backend/src/main/resources/images/" + changeFileName(file)); + File convertFile = new File(Path.imageSavePath.getPath() + changeFileName(file)); if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) try (FileOutputStream fos = new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함 @@ -41,7 +41,6 @@ public Optional localUpload(MultipartFile file) throws IOException { } return Optional.of(convertFile); } - return Optional.empty(); } diff --git a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java new file mode 100644 index 0000000..75e3afe --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java @@ -0,0 +1,14 @@ +package com.hjjang.backend.infra.uploader.component; + +import lombok.Getter; + +@Getter +public enum Path { + imageSavePath(System.getProperty("user.dir") + "/backend/src/main/resources/images/"); + + private final String path; + Path(String path) { + this.path = path; + } + +} diff --git a/backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java similarity index 72% rename from backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java rename to backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java index edfe046..c0c2dd3 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/aws/component/S3Uploader.java +++ b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.aws.component; +package com.hjjang.backend.infra.uploader.component; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.CannedAccessControlList; @@ -18,26 +18,31 @@ @Slf4j @RequiredArgsConstructor @Component -public class S3Uploader { +public class S3Uploader implements ImageUploader { private final AmazonS3Client amazonS3Client; @Value("${cloud.aws.s3.bucket}") public String bucket; // S3 버킷 이름 - public String upload(MultipartFile multipartFile, String dirName) throws IOException { + @Override + public String upload(MultipartFile multipartFile) throws IOException { File uploadFile = - convert(multipartFile) // 파일 변환할 수 없으면 에러 + this.localUpload(multipartFile) // 파일 변환할 수 없으면 에러 .orElseThrow( () -> new IllegalArgumentException("error: MultipartFile -> File convert fail")); - return upload(uploadFile, dirName); + return upload(uploadFile); + } + + @Override + public String changeFileName(MultipartFile uploadFile) { + return UUID.randomUUID() + ".png"; // 저장될 파일 이름 변환 } // S3로 파일 업로드하기 - private String upload(File uploadFile, String dirName) { - String fileName = dirName + "/" + UUID.randomUUID() + uploadFile.getName(); // S3에 저장된 파일 이름 - String uploadImageUrl = putS3(uploadFile, fileName); // s3로 업로드 + private String upload(File uploadFile) { + String uploadImageUrl = putS3(uploadFile, "static/" + uploadFile.getName()); // s3로 업로드 removeNewFile(uploadFile); return uploadImageUrl; } @@ -60,8 +65,9 @@ private void removeNewFile(File targetFile) { } // 로컬에 파일 업로드 하기 - private Optional convert(MultipartFile file) throws IOException { - File convertFile = new File(System.getProperty("user.dir") + "/" + file.getOriginalFilename()); + @Override + public Optional localUpload(MultipartFile file) throws IOException { + File convertFile = new File(Path.imageSavePath.getPath() + changeFileName(file)); if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) try (FileOutputStream fos = new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함 From ce6e87bfd66f7f875b6be88e65a9d84f4a393480 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sat, 30 Apr 2022 15:41:43 +0900 Subject: [PATCH 4/8] chore : change max filesize to 50mb --- backend/src/main/resources/application.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 34b32a3..6fe52ac 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -64,6 +64,12 @@ spring: tokenUri: https://kauth.kakao.com/oauth/token userInfoUri: https://kapi.kakao.com/v2/user/me userNameAttribute: id + + servlet: + multipart: + max-file-size: 50MB + max-request-size: 50MB + auth: tokenProperties: tokenSecretKey: asodfhwoeihro1i34u1097r09u13rqfasc12 From 61a59e7be7fc8ca5958e70b1a4e7cbed6d96582d Mon Sep 17 00:00:00 2001 From: Young-Jun Kim Date: Sat, 30 Apr 2022 18:31:48 +0900 Subject: [PATCH 5/8] Update backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java Co-authored-by: Yunkeun <70425484+Yunkeun@users.noreply.github.com> --- .../hjjang/backend/domain/image/controller/ImageController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java index fee4454..ec58cdc 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java @@ -52,7 +52,7 @@ public ResponseEntity findImage(@PathVariable Long imageId) { } @DeleteMapping("/{imageId}") - public ResponseEntity deleteIMage(@PathVariable Long imageId) { + public ResponseEntity deleteImage(@PathVariable Long imageId) { Image image = imageService.findImageById(imageId); imageService.removeImage(image); From f7fc1e38b838b80b0cb82273351eafc715bfea97 Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sat, 30 Apr 2022 22:46:39 +0900 Subject: [PATCH 6/8] =?UTF-8?q?chore=20:=20(PR=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EB=B0=98=EC=98=81)=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=8D=94=20=EC=BD=94=EB=93=9C=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0,=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=84=9C=EB=B9=84=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EB=A1=9C=EC=BB=AC=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=8D=94=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/controller/ImageController.java | 5 +-- .../backend/domain/image/dto/ImageDto.java | 23 ---------- .../domain/image/service/ImageService.java | 32 ++++++++++--- .../image/service/ImageUploader.java} | 11 ++--- .../image/service/LocalImageService.java | 45 ------------------- .../image/service/LocalImageUploader.java | 10 +++++ .../image/service}/Path.java | 2 +- .../domain/image/service/S3ImageService.java | 44 ------------------ .../service/S3ImageUploader.java} | 32 +++---------- .../uploader/component/ImageUploader.java | 16 ------- 10 files changed, 49 insertions(+), 171 deletions(-) delete mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java rename backend/src/main/java/com/hjjang/backend/{infra/uploader/component/LocalUploader.java => domain/image/service/ImageUploader.java} (88%) delete mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java create mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java rename backend/src/main/java/com/hjjang/backend/{infra/uploader/component => domain/image/service}/Path.java (81%) delete mode 100644 backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java rename backend/src/main/java/com/hjjang/backend/infra/{uploader/component/S3Uploader.java => aws/service/S3ImageUploader.java} (61%) delete mode 100644 backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java index fee4454..29a4c29 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/controller/ImageController.java @@ -2,8 +2,7 @@ import com.hjjang.backend.domain.image.domain.entity.Image; import com.hjjang.backend.domain.image.dto.ImagePathResponse; -import com.hjjang.backend.domain.image.service.LocalImageService; -import com.hjjang.backend.domain.image.service.S3ImageService; +import com.hjjang.backend.domain.image.service.ImageService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -21,7 +20,7 @@ @RequestMapping("/api/images") public class ImageController { - private final LocalImageService imageService; + private final ImageService imageService; @GetMapping() public ResponseEntity> findAllImage() { diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java b/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java deleted file mode 100644 index d0808e4..0000000 --- a/backend/src/main/java/com/hjjang/backend/domain/image/dto/ImageDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.hjjang.backend.domain.image.dto; - - -import com.hjjang.backend.domain.image.domain.entity.Image; -import lombok.*; - -import javax.validation.constraints.NotEmpty; -import java.io.IOException; - -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class ImageDto { - @NotEmpty - private String path; - - public Image toEntity() throws IOException { - return Image.builder() - .path(this.path) - .build(); - } -} diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java index 58a78aa..5b873b0 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java @@ -1,19 +1,41 @@ package com.hjjang.backend.domain.image.service; +import com.hjjang.backend.domain.image.domain.repository.ImageRepository; import com.hjjang.backend.domain.image.domain.entity.Image; +import com.hjjang.backend.domain.image.exception.ImageNotFoundException; +import com.hjjang.backend.infra.aws.service.S3ImageUploader; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import javax.transaction.Transactional; import java.io.IOException; import java.util.List; -public interface ImageService { +@Service +@RequiredArgsConstructor +@Transactional +public class ImageService { + private final ImageRepository imageRepository; - List findAll(); + private final S3ImageUploader imageUploader; - Image findImageById(Long imageId); + public List findAll() { + return imageRepository.findAll(); + } - Image uploadNewImage(MultipartFile multipartFile) throws IOException; + public Image findImageById(Long imageId) { + return imageRepository.findById(imageId).orElseThrow(ImageNotFoundException::new); + } - void removeImage(Image image); + public Image uploadNewImage(MultipartFile multipartFile) throws IOException { + return imageRepository.save(new Image(imageUploader.upload(multipartFile))); + } + + public void removeImage(Image image) { + image.removeImage(); + imageRepository.save(image); + } } diff --git a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java similarity index 88% rename from backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java rename to backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java index 1374456..46b99c2 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/LocalUploader.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java @@ -1,8 +1,8 @@ -package com.hjjang.backend.infra.uploader.component; +package com.hjjang.backend.domain.image.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; @@ -13,10 +13,9 @@ @Slf4j @RequiredArgsConstructor -@Component -public class LocalUploader implements ImageUploader { +@Service +public class ImageUploader { - @Override public String upload(MultipartFile multipartFile) throws IOException { File uploadFile = this.localUpload(multipartFile) // 파일 변환할 수 없으면 에러 @@ -25,13 +24,11 @@ public String upload(MultipartFile multipartFile) throws IOException { return uploadFile.getName(); } - @Override public String changeFileName(MultipartFile uploadFile) { return UUID.randomUUID() + ".png"; // 저장될 파일 이름 변환 } // 로컬에 파일 업로드 하기 - @Override public Optional localUpload(MultipartFile file) throws IOException { File convertFile = new File(Path.imageSavePath.getPath() + changeFileName(file)); if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java deleted file mode 100644 index a732372..0000000 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.hjjang.backend.domain.image.service; - -import com.hjjang.backend.domain.image.domain.repository.ImageRepository; -import com.hjjang.backend.domain.image.dto.ImageDto; -import com.hjjang.backend.domain.image.domain.entity.Image; -import com.hjjang.backend.domain.image.exception.ImageNotFoundException; -import com.hjjang.backend.infra.uploader.component.LocalUploader; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import javax.transaction.Transactional; -import java.io.IOException; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Transactional -public class LocalImageService implements ImageService{ - private final ImageRepository imageRepository; - private final LocalUploader imageUploader; - - @Override - public List findAll() { - return imageRepository.findAll(); - } - - @Override - public Image findImageById(Long imageId) { - return imageRepository.findById(imageId).orElseThrow(ImageNotFoundException::new); - } - - @Override - public Image uploadNewImage(MultipartFile multipartFile) throws IOException { - ImageDto imageDto = new ImageDto(imageUploader.upload(multipartFile)); - return imageRepository.save(imageDto.toEntity()); - } - - @Override - public void removeImage(Image image) { - image.removeImage(); - imageRepository.save(image); - } - -} diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java new file mode 100644 index 0000000..07a5301 --- /dev/null +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java @@ -0,0 +1,10 @@ +package com.hjjang.backend.domain.image.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +public class LocalImageUploader extends ImageUploader{} \ No newline at end of file diff --git a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/Path.java similarity index 81% rename from backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java rename to backend/src/main/java/com/hjjang/backend/domain/image/service/Path.java index 75e3afe..4e7a803 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/Path.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/Path.java @@ -1,4 +1,4 @@ -package com.hjjang.backend.infra.uploader.component; +package com.hjjang.backend.domain.image.service; import lombok.Getter; diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java deleted file mode 100644 index a77607f..0000000 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/S3ImageService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.hjjang.backend.domain.image.service; - -import com.hjjang.backend.domain.image.domain.entity.Image; -import com.hjjang.backend.domain.image.domain.repository.ImageRepository; -import com.hjjang.backend.domain.image.exception.ImageNotFoundException; -import com.hjjang.backend.infra.uploader.component.S3Uploader; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import javax.transaction.Transactional; -import java.io.IOException; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Transactional -public class S3ImageService implements ImageService { - private final ImageRepository imageRepository; - private final S3Uploader imageUploader; - - @Override - public List findAll() { - return imageRepository.findAll(); - } - - @Override - public Image findImageById(Long imageId) { - return imageRepository.findById(imageId).orElseThrow(ImageNotFoundException::new); - } - - @Override - public Image uploadNewImage(MultipartFile multipartFile) throws IOException { - return imageRepository.save( - new Image(imageUploader.upload(multipartFile)) - ); - } - - @Override - public void removeImage(Image image) { - image.removeImage(); - imageRepository.save(image); - } -} diff --git a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java b/backend/src/main/java/com/hjjang/backend/infra/aws/service/S3ImageUploader.java similarity index 61% rename from backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java rename to backend/src/main/java/com/hjjang/backend/infra/aws/service/S3ImageUploader.java index c0c2dd3..522cb79 100644 --- a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/S3Uploader.java +++ b/backend/src/main/java/com/hjjang/backend/infra/aws/service/S3ImageUploader.java @@ -1,24 +1,22 @@ -package com.hjjang.backend.infra.uploader.component; +package com.hjjang.backend.infra.aws.service; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.PutObjectRequest; +import com.hjjang.backend.domain.image.service.ImageUploader; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.util.Optional; -import java.util.UUID; @Slf4j @RequiredArgsConstructor -@Component -public class S3Uploader implements ImageUploader { +@Service +public class S3ImageUploader extends ImageUploader { private final AmazonS3Client amazonS3Client; @@ -35,11 +33,6 @@ public String upload(MultipartFile multipartFile) throws IOException { return upload(uploadFile); } - @Override - public String changeFileName(MultipartFile uploadFile) { - return UUID.randomUUID() + ".png"; // 저장될 파일 이름 변환 - } - // S3로 파일 업로드하기 private String upload(File uploadFile) { String uploadImageUrl = putS3(uploadFile, "static/" + uploadFile.getName()); // s3로 업로드 @@ -63,19 +56,4 @@ private void removeNewFile(File targetFile) { } log.info("File delete fail"); } - - // 로컬에 파일 업로드 하기 - @Override - public Optional localUpload(MultipartFile file) throws IOException { - File convertFile = new File(Path.imageSavePath.getPath() + changeFileName(file)); - if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) - try (FileOutputStream fos = - new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함 - fos.write(file.getBytes()); - } - return Optional.of(convertFile); - } - - return Optional.empty(); - } } diff --git a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java b/backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java deleted file mode 100644 index 2588416..0000000 --- a/backend/src/main/java/com/hjjang/backend/infra/uploader/component/ImageUploader.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.hjjang.backend.infra.uploader.component; - -import org.springframework.web.multipart.MultipartFile; - -import java.io.File; -import java.io.IOException; -import java.util.Optional; - -public interface ImageUploader { - - String upload(MultipartFile multipartFile) throws IOException; - - String changeFileName(MultipartFile uploadFile); - - Optional localUpload(MultipartFile file) throws IOException; -} From 36d987cfeb0d2e8cde7a43075c40a2e2444dea3b Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sat, 30 Apr 2022 22:47:36 +0900 Subject: [PATCH 7/8] =?UTF-8?q?chore=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=ED=8F=AC=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hjjang/backend/domain/image/service/ImageService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java index 5b873b0..ac506a1 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageService.java @@ -5,7 +5,6 @@ import com.hjjang.backend.domain.image.exception.ImageNotFoundException; import com.hjjang.backend.infra.aws.service.S3ImageUploader; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; From c0b0e14b0baab6cbdb9fed5136d96bce8d8abd3e Mon Sep 17 00:00:00 2001 From: 0BVer Date: Sun, 1 May 2022 00:49:14 +0900 Subject: [PATCH 8/8] =?UTF-8?q?refactor=20:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=83=81=EC=86=8D=20=EA=B4=80=EA=B3=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/image/service/ImageUploader.java | 6 +----- .../image/service/LocalImageUploader.java | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java index 46b99c2..aa15b0b 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/ImageUploader.java @@ -17,11 +17,7 @@ public class ImageUploader { public String upload(MultipartFile multipartFile) throws IOException { - File uploadFile = - this.localUpload(multipartFile) // 파일 변환할 수 없으면 에러 - .orElseThrow( - () -> new IllegalArgumentException("error: MultipartFile -> File convert fail")); - return uploadFile.getName(); + return null; } public String changeFileName(MultipartFile uploadFile) { diff --git a/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java index 07a5301..7872844 100644 --- a/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java +++ b/backend/src/main/java/com/hjjang/backend/domain/image/service/LocalImageUploader.java @@ -3,8 +3,23 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; @Slf4j @RequiredArgsConstructor @Service -public class LocalImageUploader extends ImageUploader{} \ No newline at end of file +public class LocalImageUploader extends ImageUploader{ + + @Override + public String upload(MultipartFile multipartFile) throws IOException { + File uploadFile = + this.localUpload(multipartFile) // 파일 변환할 수 없으면 에러 + .orElseThrow( + () -> new IllegalArgumentException("error: MultipartFile -> File convert fail")); + return uploadFile.getName(); + } + +} \ No newline at end of file