S3 업로드 시작 전 확인
버킷 생성 : https://jungkeung.tistory.com/44
버킷 정책 생성 : https://jungkeung.tistory.com/45
IAM 키 생성 : https://jungkeung.tistory.com/46
환경 세팅
- Intellij 2021.01
- SpringBoot 2.2.4
- Gralde
- spring-cloud-aws 2.2.1
build.gralde
- thymeleaf, lombok, JPA, Mysql, web 정도 입니다.
dependencies {
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.1.RELEASE'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'junit:junit:4.12'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
// AWS S3
compile group: 'org.springframework.cloud', name: 'spring-cloud-aws', version: '2.2.1.RELEASE', ext: 'pom'
compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile("org.springframework.boot:spring-boot-starter-jdbc")
compile("mysql:mysql-connector-java:8.0.23")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
testCompile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
aws 설정
aws 설정은 applcation,yml 파일에 작성 했습니다.
src/main/resources/application.yml
cloud:
aws:
credentials:
accessKey: 본인 ACCESS_KEY
secretKey: 본인 SECREY_KEY
s3:
bucket: 본인 버켓 이름
region:
static: 본인 설정 서버 (ex: ap-northeast-2)
stack:
auto: false
위에 stack.auto는 Spring Cloud 실행 시, 서버구성을 자동화하는 CloudFormation이 자동으로 실해되는데 이를 사용하지않겠다는 설정입니다. 안하시면 에러가 뜹니다
gitignore
- gitgnore 에 application.yml 넣어주셔야합니다.
git에 aws 키가 노출되면 엄청난 과금이 생기니 꼭 해주셔야합니다.
.gitgnore 하고 push를 하기 전에, git status로 application.yml 파일이 commit목록에 없는지 꼭확인하세요.
이제 설정이 끝났으니 코드를 구현하겠습니다
서비스 구현 - 퍼블리싱
src/main/resources/templates/gallery.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>S3 파일 업로드 테스트</title>
</head>
<body>
<h1>파일 업로드</h1> <hr>
<form th:action="@{/gallery}" method="post" enctype="multipart/form-data">
제목 : <input type="text" name="title"> <br>
파일 : <input type="file" name="file"> <br>
<button>등록하기</button>
</form>
</body>
</html>
서비스 구현 -Controller
src/main/java/com/victolee/s3exam/controller/GalleryController.java
import com.victolee.s3exam.dto.GalleryDto;
import com.victolee.s3exam.service.GalleryService;
import com.victolee.s3exam.service.S3Service;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Controller
@AllArgsConstructor
public class GalleryController {
private S3Service s3Service;
private GalleryService galleryService;
@GetMapping("/gallery")
public String dispWrite() {
return "/gallery";
}
@PostMapping("/gallery")
public String execWrite(GalleryDto galleryDto, MultipartFile file) throws IOException {
String imgPath = s3Service.upload(file);
galleryDto.setFilePath(imgPath);
galleryService.savePost(galleryDto);
return "redirect:/gallery";
}
}
- execWrite(GalleryDto galleryDto, MultipartFile file) throws IOException
form으로부터 넘어온 파일 객체를 받기 위해,MultipartFile 타입의 파라미터를 작성해줍니다.
- s3Service.upload(file)
s3Service는 AWS S3의 비즈니스 로직을 담당하며, 파일을 조작합니다.
- galleryService.savePost(galleryDto);
galleryService는 DB에 데이터를 조작하기 위한 서비스입니다.
서비스 구현 -S3Service
src/main/java/com/victolee/s3exam/service/S3Service.java
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 com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.IOException;
@Service
@NoArgsConstructor
public class S3Service {
private AmazonS3 s3Client;
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
@Value("${cloud.aws.region.static}")
private String region;
@PostConstruct
public void setS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(this.region)
.build();
}
public String upload(MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
s3Client.putObject(new PutObjectRequest(bucket, fileName, file.getInputStream(), null)
.withCannedAcl(CannedAccessControlList.PublicRead));
return s3Client.getUrl(bucket, fileName).toString();
}
}
AmazonS3Client가 deprecated됨에 따라, AmazonS3ClientBuilder를 사용했습니다.
@Value("${cloud.aws.credentials.accessKey}")
- lombok 패키지가 아닌, org.springframework.beans.factory.annotation 패키지임에 유의합니다.
- 해당 값은 application.yml에서 작성한 cloud.aws.credentials.accessKey 값을 가져옵니다.
@PostConstruct
- 의존성 주입이 이루어진 후 초기화를 수행하는 메서드이며, bean이 한 번만 초기화 될수 있도록 해줍니다.
- 이렇게 해주는 목적은 AmazonS3ClientBuilder를 통해 S3 Client를 가져와야 하는데, 자격증명을 해줘야 S3 Client를 가져올 수 있기 때문입니다.
s3Client.putObject(new PutObjectRequest(bucket, fileName, file.getInputStream(), null)
- .withCannedAcl(CannedAccessControlList.PublicRead));
- 외부에 공개할 이미지이므로, 해당 파일에 public read 권한을 추가합니다.
s3Client.getUrl(bucket, fileName).toString()
- 업로드를 한 후, 해당 URL을 DB에 저장할 수 있도록 컨트롤러로 URL을 반환합니다.
서비스 구현 -GalleryService
src/main/java/com/victolee/s3exam/service/GalleryService.java
import com.victolee.s3exam.domain.repository.GalleryRepository;
import com.victolee.s3exam.dto.GalleryDto;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@AllArgsConstructor
public class GalleryService {
private GalleryRepository galleryRepository;
public void savePost(GalleryDto galleryDto) {
galleryRepository.save(galleryDto.toEntity());
}
}
DB에 저장하는 로직입니다
서비스 구현 - GalleryRepository
src/main/java/com/victolee/s3exam/domain/repository/GalleryRepository.java
import com.victolee.s3exam.domain.entity.GalleryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface GalleryRepository extends JpaRepository<GalleryEntity, Long> {
}
서비스 구현 -GalleryEntity
src/main/java/com/victolee/s3exam/domain/entity/GalleryEntity.java
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
@Table(name = "gallery")
public class GalleryEntity {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false)
private String title;
@Column(columnDefinition = "TEXT")
private String filePath;
@Builder
public GalleryEntity(Long id, String title, String filePath) {
this.id = id;
this.title = title;
this.filePath = filePath;
}
}
서비스 구현 - GalleryDto
src/main/java/com/victolee/s3exam/dto/GalleryDto.java
import com.victolee.s3exam.domain.entity.GalleryEntity;
import lombok.*;
@Getter
@Setter
@ToString
@NoArgsConstructor
public class GalleryDto {
private Long id;
private String title;
private String filePath;
public GalleryEntity toEntity(){
GalleryEntity build = GalleryEntity.builder()
.id(id)
.title(title)
.filePath(filePath)
.build();
return build;
}
@Builder
public GalleryDto(Long id, String title, String filePath) {
this.id = id;
this.title = title;
this.filePath = filePath;
}
}
테스트
1) 파일 업로드
제대로 들어온걸 확인 할수 있습니다
더 정확한 내용이나 정보는 https://victorydntmd.tistory.com/334 여기서 확인 하실수 있습니다!
'AWS' 카테고리의 다른 글
Linux 자동 배포 (0) | 2021.06.12 |
---|---|
Linux 배포 에러 (0) | 2021.06.12 |
s3 IAM 설정하기 (0) | 2021.05.31 |
s3 버킷 정책 생성 (0) | 2021.05.31 |
s3 버킷 생성 (0) | 2021.05.31 |