본문 바로가기
해피 코딩/AWS

S3 이미지 업로드 및 다운로드

by happy-coding 2024. 10. 4.

Simple Storage Service

🔥 S3 이미지 업로드 및 다운로드 구현하기

application.yml
spring:
  application:
    name: s3_test
  cloud:
    aws:
      credentials:
        access-key: ${ACCESS_KEY}
        secret-key: ${SECRET_ACCESS_KEY}
      region:
        static: ap-northeast-2 # Asia Pacific (Seoul)

  datasource:
    url: jdbc:mysql://localhost:3306/S3-test
    username: ${MYSQL_ID}
    password: ${MYSQL_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver

s3:
  bucket-name: bucket-pra
  path: images

[ S3 이미지 업로드 구현 ]

UploadService
  • Interface
public interface UploadService {
  String uploadImage(MultipartFile uploadFile);
}
UploadSeviceImpl
  • UploadService 구현체
    • 업로드 기본 설정 및 업로드 구현 Service 로직
@Service
public class UploadServiceImpl implements UploadService {
  private final S3Client s3Client;

  private final String bucketName;
  private final String path;

  public UploadServiceImpl(S3Client s3Client, @Value("${s3.bucket-name}") String bucketName, @Value("${s3.path}") String path) {
    this.s3Client = s3Client;
    this.bucketName = bucketName;
    this.path = path;
  }

  @Override
  @SneakyThrows /// 1. Exception 제거해주는 애너테이션
  public String uploadImage(MultipartFile uploadFile) {
    // images/{파일명} 형태로 저장
    String uploadUrl = path + "/" + uploadFile.getOriginalFilename();
    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(uploadUrl)
            .build();

    RequestBody content = RequestBody.fromInputStream(
            uploadFile.getInputStream(), // 1. Exception 발생
            uploadFile.getSize()
    );

    s3Client.putObject(request, content);
    return uploadUrl;
  }
}
ImageController
@RestController
@RequestMapping("/images")
public class ImageController {
  private final UploadService uploadService;

  public ImageController(UploadService uploadService) {
    this.uploadService = uploadService;
  }

  @PostMapping
  public ResponseEntity<String> uploadImage(
          @RequestParam("file") MultipartFile file
  ) {
    uploadService.uploadImage(file);
    return ResponseEntity.ok("ok");
  }
}

[ 결과 확인 ]

Postman을 사용한 이미지 업로드
  • 이미지 업로드
    • MultipartFile 데이터는 Bodyform-data 형식으로 요청, Key를 File타입으로 변경 후 업로드 한다.


  • 업로드 성공


업로드된 이미지 버킷 확인


 

  • application.yml에서 "path"에 설정해 준 이름을 바탕으로 images라는 파일이 생성된 모습을 볼 수 있다

  • 버킷에 images/ 폴더에 docker.png 파일이 업로드된 모습을 볼 수 있다

[ S3 이미지 다운로드 구현 ]

UploadService
  • Interface
InputStream getFile(String fileName); // 다운로드 추가
UploadSeviceImpl
  • UploadService 구현체
    • 다운로드 구현 Service 로직 추가
// S3에서 파일 다운로드
@Override
public InputStream getFile(String fileName) {
  GetObjectRequest request = GetObjectRequest.builder()
          .bucket(bucketName)
          .key(getS3UploadUrl(fileName))
          .build();
  return s3Client.getObject(request);
}

private String getS3UploadUrl(String fileName) {
  // images/docker.png
  return path + "/" + fileName;
}
ImageController
  • Controller에 다운로드 추가
// S3에서 파일 다운로드
@GetMapping
public ResponseEntity<InputStreamResource> getImage(@RequestParam(value = "file") String fileName) {
  InputStream imageStream = uploadService.getFile(fileName);

  return ResponseEntity.ok()
          .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
          .contentType(MediaType.IMAGE_PNG) // 혹은 IMAGE_JPEG
          .body(new InputStreamResource(imageStream)); // imageStream을 InputStreamResource으로 감싸서 반환
}

[ 결과 확인 ]

Postman을 사용한 이미지 조회 및 다운로드
  • 이미지 다운로드

  • 다운로드 성공


S3를 사용한 이미지 업로드다운로드를 구현해 보았다.

다음번에는 더 나아가서

1. 업로드 시 이미지 사이즈 제한하기

2. API 응답 속도 향상시키기

를 실습해 보도록 하자.

 

읽어주셔서 감사합니다 😊

 

  • S3 이미지 사이즈 제한하기, API 응답 속도 향상시키

😺 Blog: https://happy-coding.tistory.com/51

 

😺 GitHub: https://github.com/mad-cost/AWS-S3-study