해당글은 java v1입니다. v2 버전은 AWS SDK v2 S3 적용하기 글을 참고해 주세요!
이전에 AWS S3 사용하기에서 S3에 이미지를 저장하는 방법을 소개했었다. 하지만 해당 방법에서 맘에 들지 않았던 부분이 파일을 저장하기 위해 서버에 먼저 파일을 read한 뒤 파일을 write하는 행동을 해야했다. 그리고 또한 파일을 S3에 업로드한 뒤에 다시 해당 파일을 delete까지 해야하는 IO가 엄청나게 많은 리소스를 잡아먹을거 같은 행동들을 해야만 했다. 그래서 파일을 저장하지 않고 바로 S3에 업로드하는 방법을 찾아봤다.
public interface S3V2Service {
int putObject(List<MultipartFile> files);
}
@Service
@RequiredArgsConstructor
@Slf4j
public class S3V2ServiceImpl implements S3V2Service{
private final Environment env;
private final AmazonS3 s3Client;
@Override
public int putObject(List<MultipartFile> files) {
String bucketName = env.getProperty("cloud.s3.bucket");
try{
for(MultipartFile file : files){
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
s3Client.putObject(new PutObjectRequest(bucketName, "juno/"+file.getOriginalFilename(), file.getInputStream(), metadata));
}
}catch(IOException ie){
log.error("파일을 읽어들이는데 에러가 발생했습니다.");
log.error(ie.getMessage());
}
return 0;
}
}
해당 메서드를 통해 file을 전송하지 않고 InputStream만으로 파일을 바로 업로드할 수 있도록 구현했다. 파일의 metadata 내용도 필요해서 해당 객체를 전송하도록 소스를 만들었다.
@RestController
@RequestMapping(value = "/v2/s3")
@RequiredArgsConstructor
public class S3V2Controller {
private final S3V2Service s3Service;
@PostMapping(value = "/put")
public ResponseEntity<CommonResponse<String>> putObject(List<MultipartFile> files){
int result = s3Service.putObject(files);
return ResponseEntity.status(HttpStatus.CREATED).body(new CommonResponse<String>(result, "성공"));
}
}
다음과 같이 controller까지 작성해서 파일을 전송해보자!
3개의 이미지를 전송했고
이미지가 모두 잘 저장된 것을 확인할 수 있었다!