[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.
💛 개인 공부 기록용 블로그입니다. 👻