스프링부트를 사용하여 AWS S3 버킷 연동하여 파일 업로드 하기
IAM사용자 키 엑세스키 생성에 이어서 스프링 부트에서 S3에 파일을 업로드할 수 있도록 구현하였다.
또한 업로드된 파일의 이름과 주소를 DB에 저장한다.
1. 먼저 dependencies에 의존성을 추가한다
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
2. application.yml 설정
spring:
jackson:
property-naming-strategy: SNAKE_CASE
datasource:
url: jdbc:mysql://localhost:3306/community?serverTimezone=Asia/Seoul
username: root
password: password
redis:
host: localhost
port: 6379
jpa:
hibernate:
ddl-auto: create
show-sql: true
properties:
hibernate:
format_sql: true
data: # spring data rest - 관련 설정
rest:
base-path: /api #endpoint start path
detection-strategy: annotated
profiles:
include: API-KEY #key가 저장된 yml 연동
cloud: # AWS 계정연동 관련설정
aws:
region:
static: ap-northeast-2
# s3:
# credentials:
# access-key: access-key
# secret-key: secret-key
stack:
auto: false
핵심은 spring.profies: 부터의 설정들이다
- spring.profiles.include : 깃에 올리지 않을 엑세스키와 시크릿키가 담긴 application-API-KEY.yml파일을 연결했다.
환경변수를 통해 키를 관리해준다면 주석처리된 부분을 해제하여 환경변수를 통해 엑세스키와 시크릿키를 할당하면 된다.
- cloud설정에서 aws관련 내용들을 적어준다
- 마지막줄 stack.auto: false는 관련 내용을 사용하지 않음으로 반드시 적어준다.
3. .gitignore 설정 (옵션)
### api key 관련 ###
/src/main/resources/application-API-KEY.yml
이렇게 추가해주면 키가담긴 yml파일이 깃에 올라가지 않는다.
4. 터미널에 git -rm -r -cached /src/main/resources/application-API-KEY.yml 입력
- 해당 명령어를 입력하면 기존 추적되던 캐시를 삭제한다.
5. Entity
@NoArgsConstructor
@Setter @Getter
@Entity
public class UploadFile{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long fileId;
private String fileName;
private String imagePath;
@ManyToOne
@JoinColumn(name = "board_id")
private Board board;
public UploadFile(String fileName, String imagePath) {
this.fileName = fileName;
this.imagePath = imagePath;
}
}
- 추후 Board엔티티와 매핑을 위해 조인컬럼을 사용하였다.
6. service
@RequiredArgsConstructor
@Service
public class S3Service {
private String S3Bucket = "kjs-project-upload"; // Bucket 이름
private final AmazonS3Client amazonS3Client;
private final UploadFileRepository uploadFileRepository;
public List<String> uploadFiles(MultipartFile[] multipartFileList) throws Exception {
List<String> imagePathList = new ArrayList<>();
for (MultipartFile multipartFile : multipartFileList) {
String fileName = multipartFile.getOriginalFilename(); // 파일 이름
long size = multipartFile.getSize(); // 파일 크기
ObjectMetadata objectMetaData = new ObjectMetadata();
objectMetaData.setContentType(multipartFile.getContentType());
objectMetaData.setContentLength(size);
// S3에 업로드
amazonS3Client.putObject(
new PutObjectRequest(S3Bucket, fileName, multipartFile.getInputStream(), objectMetaData)
.withCannedAcl(CannedAccessControlList.PublicRead)
);
String imagePath = amazonS3Client.getUrl(S3Bucket, fileName).toString(); // 접근가능한 URL 가져오기
imagePathList.add(imagePath); //String Type URL주소
//엔티티에 저장하는 로직
UploadFile uploadFile = new UploadFile();
uploadFile.setFileName(fileName);
uploadFile.setImagePath(imagePath);
uploadFileRepository.save(uploadFile);
}
return imagePathList;
}
}
7. Repository
public interface UploadFileRepository extends JpaRepository<UploadFile, Long> {}
- @Repository 는 상속받는 JPARpository에 포함되어있기 때문에 적지 않아도 된다.
8. Contorller
@RestController
@RequiredArgsConstructor
public class BoardController {
private final S3Service s3Service;
@PostMapping("/upload")
public ResponseEntity<Object> upload(@RequestParam MultipartFile[] files) throws Exception {
List<String> imagePathList = s3Service.uploadFiles(files);
return new ResponseEntity<>(imagePathList, HttpStatus.OK);
}
9. Postman 테스트

- body에 기존 Json형식으로 데이터를 넣는것이 아닌 form-data형식으로 데이터를 넣어줘야한다.
결과값으로 사진파일을 확인할 수 있는 S3주소를 리턴한다.
또한 연결된 DB를 확인해보면 해당 파일명과 S3버킷 안에있는 파일URL이 저장된 것을 확인할 수 있다.
'Study > Java Spring Boot' 카테고리의 다른 글
java.sql.SQLIntegrityConstraintViolationException: Column '컬럼명' cannot be null (0) | 2023.03.16 |
---|---|
@ModelAttribute 사용 방법 및 원리 (0) | 2023.03.15 |
스프링부트 - Json타입 카멜케이스 -> 스네이크 케이스 변환 (0) | 2023.03.14 |
QueryDSL기능 사용방법 및 설정 (검색기능) 심화 (1) | 2023.03.12 |
Security추가 후 Post 요청 403에러 해결 (0) | 2023.03.11 |