From f9c31941d9d3b0babc75032fb42d3ec4068d7dd5 Mon Sep 17 00:00:00 2001 From: Anna-Jin Date: Mon, 11 Jul 2022 15:46:13 +0900 Subject: [PATCH] =?UTF-8?q?#19=20[Update]=20=EC=97=85=EC=9E=A5=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이미지 업로드 과정에서 에러 발생!!! --- .../UserRegisterStoreController.java | 33 +++++++++ .../store/domain/UserRegisterStore.java | 4 + .../store/domain/UserRegisterStoreImg.java | 32 ++++++++ .../UserRegisterStoreImgDto.java | 13 ++++ .../userRegisterStoreRequestDto.java | 17 ++++- .../userRegisterStoreResponseDto.java | 23 +++++- .../UserRegisterStoreImgRepository.java | 9 +++ .../UserRegisterStoreRepository.java | 9 +++ .../service/UserRegisterStoreService.java | 60 +++++++++++++++ .../mpnp/baechelin/util/AmazonS3Config.java | 6 +- .../com/mpnp/baechelin/util/AwsS3Manager.java | 73 +++++++++++++++++++ 11 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/mpnp/baechelin/store/controller/UserRegisterStoreController.java create mode 100644 src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStoreImg.java create mode 100644 src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/UserRegisterStoreImgDto.java create mode 100644 src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreImgRepository.java create mode 100644 src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreRepository.java create mode 100644 src/main/java/com/mpnp/baechelin/store/service/UserRegisterStoreService.java create mode 100644 src/main/java/com/mpnp/baechelin/util/AwsS3Manager.java diff --git a/src/main/java/com/mpnp/baechelin/store/controller/UserRegisterStoreController.java b/src/main/java/com/mpnp/baechelin/store/controller/UserRegisterStoreController.java new file mode 100644 index 0000000..6f711c8 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/controller/UserRegisterStoreController.java @@ -0,0 +1,33 @@ +package com.mpnp.baechelin.store.controller; + +import com.mpnp.baechelin.store.dto.userRegisterStore.UserRegisterStoreRequestDto; +import com.mpnp.baechelin.store.service.UserRegisterStoreService; +import com.mpnp.baechelin.user.entity.user.User; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/store") +@RequiredArgsConstructor +public class UserRegisterStoreController { + + private final UserRegisterStoreService userRegisterStoreService; + + /** + * 유저 업장 등록 + * @param userRegisterStoreRequestDto + * @return + */ + @PostMapping("/register") + public ResponseEntity registerStore( + @ModelAttribute UserRegisterStoreRequestDto userRegisterStoreRequestDto) { + userRegisterStoreService.registerStore(userRegisterStoreRequestDto); + return new ResponseEntity<>("업장 등록 성공", HttpStatus.OK); + } +} diff --git a/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStore.java b/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStore.java index 29b9b2d..45e909b 100644 --- a/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStore.java +++ b/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStore.java @@ -6,6 +6,7 @@ import lombok.NoArgsConstructor; import javax.persistence.*; +import java.util.List; @Entity @Getter @@ -34,6 +35,9 @@ public class UserRegisterStore extends TimeStamped { @Column(nullable = false, length = 1) private String approach; + @OneToMany(mappedBy = "userRegisterStore", cascade = CascadeType.ALL, orphanRemoval = true) + private List userRegisterStoreImgList; + @Builder public UserRegisterStore( String name, diff --git a/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStoreImg.java b/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStoreImg.java new file mode 100644 index 0000000..520db96 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/domain/UserRegisterStoreImg.java @@ -0,0 +1,32 @@ +package com.mpnp.baechelin.store.domain; + +import com.mpnp.baechelin.util.TimeStamped; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@NoArgsConstructor +public class UserRegisterStoreImg extends TimeStamped { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @Column(nullable = false) + private String userRegisterStoreImageUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "USERREGISTERSTORE_ID", nullable = false) + private UserRegisterStore userRegisterStore; + + @Builder + public UserRegisterStoreImg(String userRegisterStoreImageUrl, UserRegisterStore userRegisterStore) { + this.userRegisterStoreImageUrl = userRegisterStoreImageUrl; + this.userRegisterStore = userRegisterStore; + } + +} diff --git a/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/UserRegisterStoreImgDto.java b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/UserRegisterStoreImgDto.java new file mode 100644 index 0000000..93d6028 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/UserRegisterStoreImgDto.java @@ -0,0 +1,13 @@ +package com.mpnp.baechelin.store.dto.userRegisterStore; + +import lombok.Getter; +import lombok.Setter; + +@Getter +public class UserRegisterStoreImgDto { + private String userRegisterStoreImageUrl; + + public UserRegisterStoreImgDto(String userRegisterStoreImageUrl) { + this.userRegisterStoreImageUrl = userRegisterStoreImageUrl; + } +} diff --git a/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreRequestDto.java b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreRequestDto.java index f3a00f9..ab8089d 100644 --- a/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreRequestDto.java +++ b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreRequestDto.java @@ -1,4 +1,19 @@ package com.mpnp.baechelin.store.dto.userRegisterStore; -public class userRegisterStoreRequestDto { +import lombok.Getter; +import lombok.Setter; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Getter +@Setter +public class UserRegisterStoreRequestDto { + private String name; + private String address; + private String elevator; + private String toilet; + private String heightDifferent; + private String approach; + private List userRegisterStoreImageList; } diff --git a/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreResponseDto.java b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreResponseDto.java index 087e84e..60e8e8d 100644 --- a/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreResponseDto.java +++ b/src/main/java/com/mpnp/baechelin/store/dto/userRegisterStore/userRegisterStoreResponseDto.java @@ -3,13 +3,32 @@ import lombok.Getter; import lombok.Setter; +import java.util.List; + @Getter -@Setter -public class userRegisterStoreResponseDto { +public class UserRegisterStoreResponseDto { private String name; private String address; private String elevator; private String toilet; private String heightDifferent; private String approach; + private List userRegisterStoreImageList; + public UserRegisterStoreResponseDto( + String name, + String address, + String elevator, + String toilet, + String heightDifferent, + String approach, + List userRegisterStoreImageList + ) { + this.name = name; + this.address = address; + this.elevator = elevator; + this.toilet = toilet; + this.heightDifferent = heightDifferent; + this.approach = approach; + this.userRegisterStoreImageList = userRegisterStoreImageList; + } } diff --git a/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreImgRepository.java b/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreImgRepository.java new file mode 100644 index 0000000..2892cf3 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreImgRepository.java @@ -0,0 +1,9 @@ +package com.mpnp.baechelin.store.repository; + +import com.mpnp.baechelin.store.domain.UserRegisterStoreImg; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRegisterStoreImgRepository extends JpaRepository { +} diff --git a/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreRepository.java b/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreRepository.java new file mode 100644 index 0000000..c18e952 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/repository/UserRegisterStoreRepository.java @@ -0,0 +1,9 @@ +package com.mpnp.baechelin.store.repository; + +import com.mpnp.baechelin.store.domain.UserRegisterStore; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRegisterStoreRepository extends JpaRepository { +} diff --git a/src/main/java/com/mpnp/baechelin/store/service/UserRegisterStoreService.java b/src/main/java/com/mpnp/baechelin/store/service/UserRegisterStoreService.java new file mode 100644 index 0000000..79d0942 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/store/service/UserRegisterStoreService.java @@ -0,0 +1,60 @@ +package com.mpnp.baechelin.store.service; + +import com.mpnp.baechelin.store.domain.UserRegisterStore; +import com.mpnp.baechelin.store.domain.UserRegisterStoreImg; +import com.mpnp.baechelin.store.dto.userRegisterStore.UserRegisterStoreRequestDto; +import com.mpnp.baechelin.store.repository.UserRegisterStoreImgRepository; +import com.mpnp.baechelin.store.repository.UserRegisterStoreRepository; +import com.mpnp.baechelin.util.AwsS3Manager; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional +public class UserRegisterStoreService { + + private final AwsS3Manager awsS3Manager; + private final UserRegisterStoreRepository userRegisterStoreRepository; + private final UserRegisterStoreImgRepository userRegisterStoreImgRepository; + + + /** + * 유저 업장 등록 + * @param userRegisterStoreRequestDto + */ + public void registerStore(UserRegisterStoreRequestDto userRegisterStoreRequestDto) { + // 업장 등록 + UserRegisterStore userRegisterStore = UserRegisterStore.builder() + .name(userRegisterStoreRequestDto.getName()) + .address(userRegisterStoreRequestDto.getAddress()) + .elevator(userRegisterStoreRequestDto.getElevator()) + .toilet(userRegisterStoreRequestDto.getToilet()) + .heightDifferent(userRegisterStoreRequestDto.getHeightDifferent()) + .approach(userRegisterStoreRequestDto.getApproach()) + .build(); + + // 업장의 이미지 여러개 등록 + // s3에 이미지 업로드 후 url 반환 + List uploadedImage = awsS3Manager.uploadFile(userRegisterStoreRequestDto.getUserRegisterStoreImageList()); + + // saveAll을 위해 userRegisterStoreImg List에 저장 + List userRegisterStoreImgList = new ArrayList<>(); + + for (String image : uploadedImage) { + UserRegisterStoreImg userRegisterStoreImg = UserRegisterStoreImg.builder() + .userRegisterStoreImageUrl(image) + .userRegisterStore(userRegisterStore) + .build(); + + userRegisterStoreImgList.add(userRegisterStoreImg); + } + + userRegisterStoreRepository.save(userRegisterStore); + userRegisterStoreImgRepository.saveAll(userRegisterStoreImgList); + } +} diff --git a/src/main/java/com/mpnp/baechelin/util/AmazonS3Config.java b/src/main/java/com/mpnp/baechelin/util/AmazonS3Config.java index 785558d..3285527 100644 --- a/src/main/java/com/mpnp/baechelin/util/AmazonS3Config.java +++ b/src/main/java/com/mpnp/baechelin/util/AmazonS3Config.java @@ -11,13 +11,13 @@ @Configuration public class AmazonS3Config { - @Value("${cloud.aws.s3.accessKey}") + @Value("${cloud.aws.credentials.access-key}") private String accessKey; - @Value("${cloud.aws.s3.secretKey}") + @Value("${cloud.aws.credentials.secret-key}") private String secretKey; - @Value("${cloud.aws.s3.region}") + @Value("${cloud.aws.region.static}") private String region; @Bean diff --git a/src/main/java/com/mpnp/baechelin/util/AwsS3Manager.java b/src/main/java/com/mpnp/baechelin/util/AwsS3Manager.java new file mode 100644 index 0000000..bbbfda1 --- /dev/null +++ b/src/main/java/com/mpnp/baechelin/util/AwsS3Manager.java @@ -0,0 +1,73 @@ +package com.mpnp.baechelin.util; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class AwsS3Manager { + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + private final AmazonS3 amazonS3; + + public List uploadFile(List multipartFile) { + List fileNameList = new ArrayList<>(); + + // 파일이 넘어오지 않으면 빈 리스트 반환 + if (multipartFile == null) { + return fileNameList; + } + + // forEach 구문을 통해 multipartFile로 넘어온 파일들 하나씩 fileNameList에 추가 + multipartFile.forEach(file -> { + String fileName = createFileName(file.getOriginalFilename()); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(file.getSize()); + objectMetadata.setContentType(file.getContentType()); + + try(InputStream inputStream = file.getInputStream()) { + amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + } catch(IOException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다."); + } + + fileNameList.add(fileName); + }); + + return fileNameList; + } + + public void deleteFile(String fileName) { + amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + } + + private String createFileName(String fileName) { // 먼저 파일 업로드 시, 파일명을 난수화하기 위해 random으로 돌립니다. + return UUID.randomUUID().toString().concat(getFileExtension(fileName)); + } + + private String getFileExtension(String fileName) { // file 형식이 잘못된 경우를 확인하기 위해 만들어진 로직이며, 파일 타입과 상관없이 업로드할 수 있게 하기 위해 .의 존재 유무만 판단하였습니다. + try { + return fileName.substring(fileName.lastIndexOf(".")); + } catch (StringIndexOutOfBoundsException e) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다."); + } + } +}