
AWS가 제공하는 Simple Storage Service(S3)로 업계 최고의 확장성, 데이터 가용성, 보안 및 성능을 제공하는 객체 스토리지 서비스입니다.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
버킷 및 자격정보 입력
cloud.aws.credentials.access-key=S3 ACCESS-KEY
cloud.aws.credentials.secret-key=S3 SECRET-KEY
cloud.aws.region.static=ap-northeast-2 (S3 버킷 지역)
cloud.aws.s3.domain=S3 도메인 주소
cloud.aws.s3.bucket=S3 버킷 이름
cloud.aws.stack.auto=false
Spring Boot S3 설정 정보 연결
S3Utils.java
@Service
public class S3Utils {
private AmazonS3 amazonS3;
@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;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
// AWS S3 자격 증명 지정
@PostConstruct
public void setAmazonS3() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accesskey, secretKey);
amazonS3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(region)
.build();
}
}
S3Utils.java 클래스에 폴더 생성, 파일 업로드, 파일 삭제 기능 추가
// 폴더 생성
public void createFolder(String bucketName, String folderName) {
amazonS3.putObject(bucketName, folderName + "/", new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
}
// 다중 파일 업로드
public void fileUpload(List<MultipartFile> files, List<String> fileList) throws Exception {
if(amazonS3 != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date date = new Date();
String today = sdf.format(date);
if(!files.isEmpty()) {
createFolder(bucket + "/contact", today);
}
ObjectMetadata objectMetadata = new ObjectMetadata();
for(int i=0; i<files.size(); i++) {
objectMetadata.setContentType(files.get(i).getContentType());
objectMetadata.setContentLength(files.get(i).getSize());
objectMetadata.setHeader("filename", files.get(i).getOriginalFilename());
amazonS3.putObject(new PutObjectRequest(bucket + "/contact/" + today, fileList.get(i), files.get(i).getInputStream(), objectMetadata));
}
} else {
throw new AppException(ErrorType.aws_credentials_fail, null);
}
}
// 다중 파일 삭제
public void fileDelete(String filePath, String fileName) {
if(amazonS3 != null) {
amazonS3.deleteObject(new DeleteObjectRequest(filePath, fileName));
} else {
throw new AppException(ErrorType.aws_credentials_fail, null);
}
}
실제 DB에 경로를 저장함과 동시에 S3에 파일 업로드까지 하는 로직 구현
public int fileUpload(String auth, List<MultipartFile> files, String contactType, String contactTitle, String contactTxt) throws Exception {
// 현재 날짜로 폴더 생성
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date date = new Date();
String today = sdf.format(date);
String userId = jwtTokenUtil.getUserIdFromToken(auth); // 토큰을 이용해 사용자 ID 찾기
List<String> fileList = Lists.newArrayList();
FileModel fileModel = new FileModel();
// AWS S3에 업로드 될 파일의 URL을 DB에 넣기 위해 URL 경로 생성
List<String> urlList = Lists.newArrayList();
if(files != null && files.size() > 0){
for (MultipartFile file : files) {
String fileRandomName = HashUtils.generateRandomKey(16);
String fileOriginName = file.getOriginalFilename();
String fileExtension = fileOriginName.substring(fileOriginName.lastIndexOf("."));
String fileFullName = fileRandomName + "_" + userId + fileExtension;
String fileFullPath = "/contact/" + today + "/" + fileFullName;
urlList.add(fileFullPath);
}
// AWS S3 파일 업로드를 위해 DB에 들어갈 URL 경로에서 파일명만 추출
if(urlList.size() > 0){
for(int i = 0; i<urlList.size(); i++){
fileList.add(urlList.get(i).substring(urlList.get(i).lastIndexOf("/")+1));
if(i == 0){
fileModel.setContact_pic_url_1(urlList.get(i));
} else if(i == 1){
fileModel.setContact_pic_url_2(urlList.get(i));
}
}
}
}
fileModel.setContact_type(contactType);
fileModel.setContact_title(contactTitle);
fileModel.setContact_txt(contactTxt);
fileModel.setContact_answer_status(0);
fileModel.setUser_id(userId);
int result = fileDao.fileUpload(fileModel);
// AWS S3에 파일 업로드 하기 위해 파일 목록과 사용자 ID를 넘겨주면서 S3Utils의 fileUpload 호출
if(fileList.size() > 0){
s3Utils.fileUpload(files, fileList);
}
return result;
}
AWS S3에 업로드된 파일의 삭제는 경로, 폴더 날짜, 사진명을 기준으로 처리
s3Utils.fileDelete(bucket + "/contact/" + folderDt, picName);
MultipartFile을 List 형태로 받아 다중 파일 업로드가 가능하도록 구현
@RequestMapping(value="/fileUpload", method=RequestMethod.POST)
public BaseModel fileUpload(@RequestHeader("Authorization") String auth,
@RequestParam("files") List<MultipartFile> files,
@RequestParam("contact_type") String contactType,
@RequestParam("contact_title") String contactTitle,
@RequestParam("contact_txt") String contactTxt) throws Exception {
BodyModel body = new BodyModel();
body.setBody(fileService.fileUpload(auth, files, contactType, contactTitle, contactTxt));
return ok(body);
}