cloud:
aws:
credentials:
access-key: ${aws_access_key}
secret-key: ${aws_secret_key}
region:
static: ${aws_region}
미리 만들어 둔 AWS S3와 연결하기 위해 필요한 값들을 지정했다
두개의 키는 IAM 계정의 정보
@PostMapping
public ResponseEntity<ApiResponse<?>> createCard(
@RequestPart("data") CreateCardDto.Request request,
@RequestPart("file") MultipartFile file,
@AuthenticationPrincipal AuthUser authUser)
throws IOException {
Card card = cardService.createCard(authUser, request, file);
return ResponseEntity.ok(ApiResponse.success(new CreateCardDto.Response(card)));
}
Controller 에서는 파일과 JSON 데이터를 동시에 처리할 수 있는 @RequestPart 를 사용
public String uploadFile(MultipartFile file) throws IOException {
// 파일 검증 (크기와 형식)
validateFile(file);
// 고유한 파일 이름 생성
String fileName = generateFileName(file);
try {
// S3에 파일 업로드
s3Client.putObject(
PutObjectRequest.builder().bucket(bucketName).key(fileName).build(),
RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
} catch (S3Exception e) {
throw new InvalidRequestException("Failed to upload the file to S3");
}
return fileName;
}
입력받은 파일은 파일 업로드와 데이터 전송을 효율적으로 처리할 수 있는 MultipartFile로 처리
이미지, PDF, CSV 등 여러 종류의 파일을 처리할 수 있는 Spring에서 파일을 간편하게 처리할 수 있는 고수준의 유틸리티
이 외의 파일 업로드를 처리하기 위한 클래스는
- Servlet API (HttpServletRequest 사용)
- Apache Commons FileUpload
- Standard InputStream/OutputStream
- Spring WebFlux (Reactive Programming)
// 파일 검증 로직
private void validateFile(MultipartFile file) {
if (file.isEmpty()) {
throw new InvalidRequestException("파일이 비어 있습니다.");
}
// 파일 크기 제한 (5MB 이하)
if (file.getSize() > 5 * 1024 * 1024) { // 5MB 제한
throw new InvalidRequestException("파일 크기는 최대 5MB입니다.");
}
// 지원되는 MIME 타입 목록
String contentType = file.getContentType();
if (!isSupportedContentType(contentType)) {
throw new InvalidRequestException("지원되지 않는 파일 형식입니다.");
}
}
// 지원되는 파일 형식 확인
private boolean isSupportedContentType(String contentType) {
return contentType.equals("image/jpeg")
|| contentType.equals("image/png")
|| contentType.equals("application/pdf")
|| contentType.equals("text/csv");
}
파일 검증 메소드로 업로드 파일 크기와 형식을 검증
AWS의 기본 업로드 제한이 사실 1MB로 제한되어 있어서 최대 5MB는 아니다...
// 고유한 파일 이름 생성
private String generateFileName(MultipartFile file) {
return UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
}
파일 이름 충돌과, 보안을 위한 파일 이름 생성 메소드
UUID와 원본 파일 이름을 조합하여 고유한 파일 이름을 생성
import java.io.IOException;
import java.util.UUID;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.sparta.springtrello.domain.common.exception.InvalidRequestException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
@Service
public class FileUploadService {
private final S3Client s3Client;
private final String bucketName = "버킷의이름을이곳에넣는다"; // S3 버킷 이름
public FileUploadService(S3Client s3Client) {
this.s3Client = s3Client;
}
public String uploadFile(MultipartFile file) throws IOException {
// 파일 검증 (크기와 형식)
validateFile(file);
// 고유한 파일 이름 생성
String fileName = generateFileName(file);
try {
// S3에 파일 업로드
s3Client.putObject(
PutObjectRequest.builder().bucket(bucketName).key(fileName).build(),
RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
} catch (S3Exception e) {
throw new InvalidRequestException("Failed to upload the file to S3");
}
return fileName;
}
// 파일 검증 로직
private void validateFile(MultipartFile file) {
if (file.isEmpty()) {
throw new InvalidRequestException("파일이 비어 있습니다.");
}
// 파일 크기 제한 (5MB 이하)
if (file.getSize() > 5 * 1024 * 1024) { // 5MB 제한
throw new InvalidRequestException("파일 크기는 최대 5MB입니다.");
}
// 지원되는 MIME 타입 목록
String contentType = file.getContentType();
if (!isSupportedContentType(contentType)) {
throw new InvalidRequestException("지원되지 않는 파일 형식입니다.");
}
}
// 지원되는 파일 형식 확인
private boolean isSupportedContentType(String contentType) {
return contentType.equals("image/jpeg")
|| contentType.equals("image/png")
|| contentType.equals("application/pdf")
|| contentType.equals("text/csv");
}
// 고유한 파일 이름 생성
private String generateFileName(MultipartFile file) {
return UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
}
}
전체 코드
String fileUrl = fileUploadService.uploadFile(file);
card.addFile(file.getOriginalFilename(), fileUrl);
Service에서는 파일 이름과 정상 업로드 후 출력된 url값을 DB에 저장한다
'TIL' 카테고리의 다른 글
Java SpringBoot Swagger 적용하기 | Swagger GET Method RequestBody | Swagger Request Form (0) | 2024.10.27 |
---|---|
Spring Boot AOP 사용하여 Slack 사용자 멘션하기 (0) | 2024.10.18 |
QueryDSL (0) | 2024.10.17 |
Spring boot AWS S3 image, file upload (0) | 2024.10.15 |
git repository commit 기록 전부 삭제 (0) | 2024.10.11 |