Skip to content

Commit

Permalink
Merge pull request #74 from cosmos-1885/feature/1-branch-account
Browse files Browse the repository at this point in the history
S3 적용
  • Loading branch information
sjmjys954646 authored Nov 8, 2023
2 parents dcada9a + 84af5fb commit 09c8ebb
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 139 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ out/

### VS Code ###
.vscode/

### .yml files ###
src/main/resources/application.yml
src/main/resources/application-ide.yml
src/main/resources/application-local.yml
src/main/resources/application-prod.yml
src/main/resources/application-test.yml
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ dependencies {
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
implementation 'com.fasterxml.jackson.core:jackson-databind'

// S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

implementation 'org.springframework.boot:spring-boot-devtools'

// local, test : h2
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/example/demo/GardenBeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
@EnableJpaAuditing
@SpringBootApplication
public class GardenBeApplication {
static {
System.setProperty("com.amazonaws.sdk.disableEc2Metadata", "true");
}

public static void main(String[] args) {
SpringApplication.run(GardenBeApplication.class, args);
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/com/example/demo/config/s3/S3Uploader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.example.demo.config.s3;

import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
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.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Component
@RequiredArgsConstructor
public class S3Uploader {
@Value("${cloud.aws.s3.bucket}")
private String s3Bucket;

private final AmazonS3Client amazonS3Client;

public String uploadFile(MultipartFile multipartFile) throws IOException {

String originalFilename = multipartFile.getOriginalFilename();

ObjectMetadata objectMetaData = new ObjectMetadata();
objectMetaData.setContentType(multipartFile.getContentType());
objectMetaData.setContentLength(multipartFile.getSize());

// S3에 업로드
amazonS3Client.putObject(
new PutObjectRequest(s3Bucket, originalFilename, multipartFile.getInputStream(), objectMetaData)
.withCannedAcl(CannedAccessControlList.PublicRead));

String imagePath = amazonS3Client.getUrl(s3Bucket, originalFilename).toString(); // 접근가능한 URL 가져오기

return imagePath;
}

public void deleteFile(String fileName) throws IOException {
try{
amazonS3Client.deleteObject(s3Bucket, fileName);
} catch (SdkClientException e) {
throw new IOException("Error deleting file from S3", e);
}
}
}
30 changes: 30 additions & 0 deletions src/main/java/com/example/demo/config/s3/S3config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.demo.config.s3;

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 S3config {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;

@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;

@Value("${cloud.aws.region.static}")
private String region;

@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
.build();
}
}
14 changes: 4 additions & 10 deletions src/main/java/com/example/demo/user/UserRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,14 @@ public static class SignUpDTO {
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$")
private String phone;

// 프로필 이미지의 경우, 추후 변경 예정
private String profileImage;

@NotNull(message = "역할을 선택해주세요.")
private Role role;

@NotNull(message = "관심 분야를 선택해주세요.")
@Size(min = 1, max = 3)
private List<String> categoryList;

public User toEntity() {
public User toEntity(String profileImageURL) {
return User.builder()
.firstName(firstName)
.lastName(lastName)
Expand All @@ -69,7 +66,7 @@ public User toEntity() {
.introduction(introduction)
.birthDate(birthDate)
.phone(phone)
.profileImage(profileImage)
.profileImage(profileImageURL)
.role(role)
.build();
}
Expand Down Expand Up @@ -123,17 +120,14 @@ public static class ProfileUpdateDTO {
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$")
private String phone;

// 프로필 이미지의 경우, 추후 변경 예정
private String profileImage;

@NotNull(message = "역할을 선택해주세요.")
private Role role;

@NotNull(message = "관심 분야를 선택해주세요.")
@Size(min = 1, max = 3)
private List<String> categoryList;

public User toEntity() {
public User toEntity(String profileImageURL) {
return User.builder()
.firstName(firstName)
.lastName(lastName)
Expand All @@ -142,7 +136,7 @@ public User toEntity() {
.introduction(introduction)
.birthDate(birthDate)
.phone(phone)
.profileImage(profileImage)
.profileImage(profileImageURL)
.role(role)
.build();
}
Expand Down
15 changes: 9 additions & 6 deletions src/main/java/com/example/demo/user/UserRestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
Expand All @@ -35,9 +38,9 @@ public ResponseEntity<?> emailCheck(@RequestBody @Valid UserRequest.EmailCheckDT
}

@Operation(summary = "회원가입", description = "회원가입")
@PostMapping(value = "/users/signup")
public ResponseEntity<?> signup(@RequestBody @Valid UserRequest.SignUpDTO requestDTO, Errors errors) {
userService.signup(requestDTO);
@PostMapping(value = "/users/signup", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<?> signup(@RequestPart @Valid UserRequest.SignUpDTO requestDTO, Errors errors, @RequestPart MultipartFile file) throws IOException {
userService.signup(requestDTO, file);
return ResponseEntity.status(HttpStatus.OK).body(ApiResponseBuilder.successWithNoContent());
}

Expand Down Expand Up @@ -83,9 +86,9 @@ public ResponseEntity<?> passwordCheck(@RequestBody @Valid UserRequest.PasswordC
}

@Operation(summary = "마이 페이지 프로필 수정", description = "마이 페이지에서 프로필 수정")
@PutMapping(value = "/profiles")
public ResponseEntity<?> profileUpdate(@RequestBody @Valid UserRequest.ProfileUpdateDTO requestDTO, Errors errors, @AuthenticationPrincipal CustomUserDetails userDetails) {
UserResponse.ProfileDTO responseDTO = userService.updateProfile(userDetails, requestDTO);
@PutMapping(value = "/profiles", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<?> profileUpdate(@RequestPart @Valid UserRequest.ProfileUpdateDTO requestDTO, Errors errors, @RequestPart MultipartFile file, @AuthenticationPrincipal CustomUserDetails userDetails) throws IOException {
UserResponse.ProfileDTO responseDTO = userService.updateProfile(userDetails, requestDTO, file);
return ResponseEntity.status(HttpStatus.OK).body(ApiResponseBuilder.success(responseDTO));
}
}
21 changes: 17 additions & 4 deletions src/main/java/com/example/demo/user/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.demo.config.auth.CustomUserDetails;
import com.example.demo.config.errors.exception.Exception400;
import com.example.demo.config.errors.exception.Exception404;
import com.example.demo.config.s3.S3Uploader;
import com.example.demo.interest.Interest;
import com.example.demo.interest.InterestJPARepository;
import com.example.demo.config.jwt.JWTTokenProvider;
Expand All @@ -16,7 +17,9 @@
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
Expand All @@ -29,6 +32,7 @@
@Service
public class UserService {

private final S3Uploader s3Uploader;
private final PasswordEncoder passwordEncoder;
private final UserJPARepository userJPARepository;
private final RefreshTokenJPARepository refreshTokenJPARepository;
Expand All @@ -43,9 +47,12 @@ public void emailCheck(UserRequest.EmailCheckDTO requestDTO) {
}

@Transactional
public void signup(UserRequest.SignUpDTO requestDTO) {
public void signup(UserRequest.SignUpDTO requestDTO, MultipartFile file) throws IOException {
String profileImageURL = s3Uploader.uploadFile(file);
System.out.println(profileImageURL);

requestDTO.setPassword(passwordEncoder.encode(requestDTO.getPassword()));
User user = userJPARepository.save(requestDTO.toEntity());
User user = userJPARepository.save(requestDTO.toEntity(profileImageURL));

List<UserInterest> userInterestList = new ArrayList<>();
List<String> categoryList = requestDTO.getCategoryList();
Expand Down Expand Up @@ -117,10 +124,16 @@ public void passwordCheck(UserRequest.PasswordCheckDTO requestDTO, CustomUserDet
}

@Transactional
public UserResponse.ProfileDTO updateProfile(CustomUserDetails userDetails, UserRequest.ProfileUpdateDTO requestDTO) {
public UserResponse.ProfileDTO updateProfile(CustomUserDetails userDetails, UserRequest.ProfileUpdateDTO requestDTO, MultipartFile file) throws IOException {
User user = userJPARepository.findById(userDetails.getUser().getId())
.orElseThrow(() -> new Exception404("해당 사용자가 존재하지 않습니다."));
user = user.updateProfile(requestDTO.toEntity());

String profileImageURL = user.getProfileImage();
String key = profileImageURL.split("/")[3];
s3Uploader.deleteFile(key);

String newProfileImageURL = s3Uploader.uploadFile(file);
user = user.updateProfile(requestDTO.toEntity(newProfileImageURL));

List<String> userCategoryList = userInterestJPARepository.findAllById(user.getId()).stream()
.map(interest -> interest.getInterest().getCategory())
Expand Down
32 changes: 0 additions & 32 deletions src/main/resources/application-ide.yml

This file was deleted.

27 changes: 0 additions & 27 deletions src/main/resources/application-local.yml

This file was deleted.

30 changes: 0 additions & 30 deletions src/main/resources/application-prod.yml

This file was deleted.

27 changes: 0 additions & 27 deletions src/main/resources/application-test.yml

This file was deleted.

3 changes: 0 additions & 3 deletions src/main/resources/application.yml

This file was deleted.

0 comments on commit 09c8ebb

Please sign in to comment.