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 |