Merge branch 'be/feat/s3/59-s3' into 'be/develop'
Feat: S3 이미지 업로드 서비스 - S11P21S002-59 See merge request s11-s-project/S11P21S002!23
This commit is contained in:
commit
617ad12dd2
@ -59,9 +59,13 @@ dependencies {
|
||||
// Redis
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
|
||||
|
||||
//Swagger
|
||||
// Swagger
|
||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
|
||||
|
||||
// AWS
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
|
||||
|
||||
// Test
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
|
||||
testImplementation 'org.mockito:mockito-core:3.9.0'
|
||||
testImplementation 'org.mockito:mockito-junit-jupiter:3.9.0'
|
||||
|
@ -53,18 +53,13 @@ public class JwtTokenService {
|
||||
}
|
||||
|
||||
public JwtToken generateTokenByRefreshToken(String refreshToken) throws Exception {
|
||||
log.debug("생성");
|
||||
|
||||
if (isTokenExpired(refreshToken)) {
|
||||
throw new CustomException(ErrorCode.REFRESH_TOKEN_EXPIRED);
|
||||
}
|
||||
|
||||
if (!isRefreshToken(refreshToken)) {
|
||||
throw new CustomException(ErrorCode.INVALID_REFRESH_TOKEN);
|
||||
}
|
||||
|
||||
log.debug("유효성 통과");
|
||||
|
||||
Claims claims = parseClaims(refreshToken);
|
||||
String username = claims.getSubject();
|
||||
int memberId = claims.get("id", Integer.class);
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.worlabel.global.config;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
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}")
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 사용자 정보가 담긴 AmazonS3 Bean 주입
|
||||
*/
|
||||
@Bean
|
||||
public AmazonS3 amazonS3() {
|
||||
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
|
||||
return AmazonS3ClientBuilder.
|
||||
standard()
|
||||
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||
.withRegion(region)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ public enum ErrorCode {
|
||||
BAD_REQUEST(HttpStatus.BAD_REQUEST, 1002, "잘못된 요청입니다. 요청을 확인해주세요."),
|
||||
EMPTY_REQUEST_PARAMETER(HttpStatus.BAD_REQUEST, 1003, "필수 요청 파라미터가 입력되지 않았습니다."),
|
||||
INVALID_URL(HttpStatus.BAD_REQUEST, 1004, "제공하지 않는 주소입니다. 확인해주세요"),
|
||||
FAIL_TO_CREATE_FILE(HttpStatus.BAD_REQUEST,1005 ,"파일 업로드에 실패하였습니다. 다시 한번 확인해주세요"),
|
||||
|
||||
// Auth & User - 2000
|
||||
USER_NOT_FOUND(HttpStatus.NOT_FOUND, 2000, "해당 ID의 사용자를 찾을 수 없습니다."),
|
||||
@ -34,8 +35,8 @@ public enum ErrorCode {
|
||||
PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 4000, "프로젝트를 찾을 수 없습니다"),
|
||||
|
||||
// Participant - 5000
|
||||
PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 접근 권한이 없습니다.")
|
||||
;
|
||||
PARTICIPANT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, 5000, "해당 프로젝트에 접근 권한이 없습니다."),
|
||||
|
||||
;
|
||||
|
||||
private final HttpStatus status;
|
||||
|
@ -0,0 +1,97 @@
|
||||
package com.worlabel.global.service;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.ObjectMetadata;
|
||||
import com.amazonaws.services.s3.model.PutObjectRequest;
|
||||
import com.amazonaws.util.IOUtils;
|
||||
import com.worlabel.global.exception.CustomException;
|
||||
import com.worlabel.global.exception.ErrorCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class S3UploadService {
|
||||
|
||||
/**
|
||||
* S3 버킷 이름
|
||||
*/
|
||||
@Value("${cloud.aws.s3.bucket}")
|
||||
private String bucket;
|
||||
|
||||
/**
|
||||
* S3 인스턴스
|
||||
*/
|
||||
private final AmazonS3 amazonS3;
|
||||
|
||||
/**
|
||||
* prefix 주소
|
||||
*/
|
||||
@Value("${cloud.aws.url}")
|
||||
private String url;
|
||||
|
||||
|
||||
/**
|
||||
* 파일이 존재하는지 확인
|
||||
*/
|
||||
public String upload(MultipartFile image) {
|
||||
if (image.isEmpty() || Objects.isNull(image.getOriginalFilename())) {
|
||||
throw new CustomException(ErrorCode.EMPTY_FILE);
|
||||
}
|
||||
return url + uploadImage(image);
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 업로드
|
||||
*/
|
||||
private String uploadImage(MultipartFile image) {
|
||||
try {
|
||||
return uploadToS3(image);
|
||||
} catch (IOException e) {
|
||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AWS S3 이미지 업로드
|
||||
*/
|
||||
private String uploadToS3(MultipartFile image) throws IOException {
|
||||
String originalFileName = image.getOriginalFilename(); // 원본 파일 이름
|
||||
String extension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1); // 파일 확장자
|
||||
|
||||
// UUID를 사용하여 고유한 파일 이름 생성
|
||||
String s3FileName = UUID.randomUUID().toString().substring(0, 14);
|
||||
|
||||
// MultipartFile의 InputStream을 가져온 뒤, 바이트 배열로 변환
|
||||
byte[] bytes = IOUtils.toByteArray(image.getInputStream());
|
||||
|
||||
ObjectMetadata metadata = new ObjectMetadata(); // S3에 업로드할 파일의 메타데이터 설정
|
||||
metadata.setContentType("image/" + extension); // 콘텐츠 타입 설정
|
||||
metadata.setContentLength(bytes.length); // 콘텐츠 길이 설정
|
||||
|
||||
log.debug("metadata : {}",metadata);
|
||||
// 바이트 배열을 사용하여 ByteArrayInputStream 생성
|
||||
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) {
|
||||
// S3에 파일 업로드 요청 생성
|
||||
PutObjectRequest putRequest = new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata);
|
||||
log.debug("요청 : {}",putRequest);
|
||||
amazonS3.putObject(putRequest); // S3 파일 업로드
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||
}
|
||||
URL url = amazonS3.getUrl(bucket, s3FileName);
|
||||
log.debug("url :{}",url);
|
||||
return url.getPath();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user