on
AWS S3 클라우드 스토리지 파일(이미지)저장
AWS S3 클라우드 스토리지 파일(이미지)저장
이미지 등의 미디어 파일을 어디에 저장하면 좋을까 고민하다 S3라는 서비스를 알게 되었다. 바로 적용해보자.
S3 버킷 만드는 과정은 쉽기도 하고 여기서는 자바 코드에 집중하겠다.
먼저 의존성과 설정파일을 준비한다.
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
cloud: aws: credentials: accessKey: 액세스키 secretKey: 비밀액세스키 s3: bucket: classy-bucket region: static: ap-northeast-2 stack: auto: false
그리고 설정 클래스 작성.
@Configuration public class AmazonS3Config { @Value("${cloud.aws.credentials.access-key}") private String accessKey; @Value("${cloud.aws.credentials.secret-key}") private String secretKey; @Value("${cloud.aws.region.static}") private String region; @Bean public AmazonS3Client amazonS3Client() { BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey); return (AmazonS3Client) AmazonS3ClientBuilder.standard() .withRegion(region) .withCredentials(new AWSStaticCredentialsProvider(awsCreds)) .build(); } }
@Value로 yml설정 파일의 정보를 불러오고 s3 클라이언트를 빈으로 만든다.
파일을 업로드해주는 클래스 생성.
Log4j2 @RequiredArgsConstructor @Service public class S3Component { private final AmazonS3Client amazonS3Client; private final S3fileService s3fileService; @Value("${cloud.aws.s3.bucket}") public String bucket; // S3 버킷 이름 public String upload(MultipartFile multipartFile, String dirName) throws IOException { File uploadFile = convert(multipartFile) // 파일 변환할 수 없으면 에러 .orElseThrow(() -> new IllegalArgumentException("error: MultipartFile -> File convert fail")); return upload(uploadFile, dirName); } // S3로 파일 업로드하기 private String upload(File uploadFile, String dirName) { String fileName = dirName + "/" + UUID.randomUUID() + "\\+" + uploadFile.getName(); // S3에 저장된 파일 이름 log.error("s3 start"); String uploadImageUrl = putS3(uploadFile, fileName); // s3로 업로드 removeNewFile(uploadFile); return uploadImageUrl; } // S3로 업로드 private String putS3(File uploadFile, String fileName) { amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead)); return amazonS3Client.getUrl(bucket, fileName).toString(); } // 로컬에 저장된 이미지 지우기 private void removeNewFile(File targetFile) { if (targetFile.delete()) { log.info("File delete success"); return; } log.info("File delete fail"); } // 로컬에 파일 업로드 하기 private Optional convert(MultipartFile file) throws IOException { File convertFile = new File(System.getProperty("user.dir") + "/" + file.getOriginalFilename()); if (convertFile.createNewFile()) { // 바로 위에서 지정한 경로에 File이 생성됨 (경로가 잘못되었다면 생성 불가능) try (FileOutputStream fos = new FileOutputStream(convertFile)) { // FileOutputStream 데이터를 파일에 바이트 스트림으로 저장하기 위함 fos.write(file.getBytes()); } return Optional.of(convertFile); } return Optional.empty(); } }
이제 컨트롤러 에서 업로드할 파일을 받아와 진행하면 된다.
@PostMapping(value = "/image/upload") public ResponseEntity> imageUpload(@RequestParam("image") MultipartFile multipartFile) { Map map = new LinkedHashMap<>(); try { s3Component.upload(multipartFile,"classyImage"); } catch (Exception e){ map.put("ErrorCode", e.toString()); return ResponseEntity.internalServerError().body(map); } map.put("SuccessCode","ImageUploadSuccess"); return ResponseEntity.ok().body(map); }
원래는 s3에 업로드 함과 동시에 db에 파일 이름을 저장하고 싶었는데 @Service 클래스에서 @Service클래스를 DI하는데 NullPointerException 에러가 자꾸나서 해결중이다. 아직 스프링 컨테이너에 대한 이해가 부족한듯 하다.
from http://sbed307.tistory.com/25 by ccl(A) rewrite - 2021-11-28 15:27:54