[S3] s3에 이미지 리스트(List) 업로드하기
이전 글은 이미지 하나를 업로드 할 수 있는 api를 구현했다.
이번에는 이미지 리스트(List<MultipartFile>)를 업로드 할 수 있도록 변경해보자.
우선, 기존에 작성한 ImageService.java와 S3Uploader.java는 삭제하였다.
코드 수정
S3Service 작성
public class S3Service {
List<String> uploadImage(List<MultipartFile> multipartFile, String dirName, Post post);
}
S3ServiceImpl 작성
@Service
@RequiredArgsConstructor
@Slf4j
public class S3ServiceImpl implements S3Service {
private final AmazonS3Client amazonS3Client;
private final ImageRepository imageRepository;
@Value("${cloud.aws.s3.bucket}")
public String bucket;
// s3에 파일 업로드
public List<String> uploadImage(List<MultipartFile> multipartFile, String dirName, Post post) {
List<String> fileNameList = new ArrayList<>();
List<String> imageUrl = new ArrayList<>();
// forEach 구문을 통해 multipartFile 로 넘어온 파일들 하나씩 fileNameList 에 추가
multipartFile.forEach(file -> {
String fileName = createFileName(file.getOriginalFilename(), dirName);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.getSize());
objectMetadata.setContentType(file.getContentType());
// S3로 업로드
try (InputStream inputStream = file.getInputStream()) {
amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch (IOException e) {
throw new CustomException(FILE_CAN_NOT_UPLOAD);
}
imageUrl.add(amazonS3Client.getUrl(bucket, fileName).toString());
fileNameList.add(fileName);
});
try {
saveUrl(imageUrl, post);
} catch (IOException e) {
e.printStackTrace();
}
return fileNameList;
}
// db에 uri 저장
public void saveUrl(List<String> imageUrls, Post post) throws IOException {
for (String imageUrl : imageUrls) {
Image img = new Image();
img.setImgurl(imageUrl);
img.setPost(post);
imageRepository.save(img);
}
}
private String createFileName(String originalName, String dirName) {
return dirName + "/" + UUID.randomUUID() + originalName;
}
}
BoardController 수정
@RequiredArgsConstructor
@RestController
@RequestMapping
("/board")
@Slf4j
public class BoardController {
private final PostService postService;
private final S3Service s3Service;
@ApiOperation(value = "게시글 등록", notes = "Amazon S3에 파일 업로드")
@PostMapping(value = "/save", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public Response uploadFile(@RequestPart @Valid PostSaveReqDto requestDto,
@ApiParam("파일들 (여러 파일 업로드 가능)") @RequestPart(required = false) List<MultipartFile> multipartFile) {
Post post = postService.save(requestDto);
if (multipartFile != null) {
s3Service.uploadImage(multipartFile, "test2", post);
}
return new Response("OK", "게시글 등록에 성공했습니다");
}
}
uploadImage 메소드의 두번째 파라미터 (위의 예시에서는 test2)의 이름에 따라 S3 bucket 내부에 이미지를 담을 해당 이름의 directory가 생성된다.
포스트맨 테스트

KEY에는 컨트롤러의 uploadFile의 파라미터 이름(requestDto와 multipartFile)을 작성해주고,
VALUE에는 게시글 내용(TEXT)과 이미지 파일(FILE)을 첨부하는 것까지는 이전과 같다.
하지만 이미지(multipartFile)의 CONTENT TYPE에는 위 사진과 같이 값을 집어넣지 않아도 된다.

AWS S3에 다음과 같이 두 개의 파일이 올라간 것을 확인할 수 있다.

또한, mysql db의 Image 테이블에도 두 개의 컬럼이 추가되었음을 확인할 수 있다!😃
Ref.
💛 개인 공부 기록용 블로그입니다. 👻