1 분 소요

이전 글은 이미지 하나를 업로드 할 수 있는 api를 구현했다.
이번에는 이미지 리스트(List<MultipartFile>)를 업로드 할 수 있도록 변경해보자.

우선, 기존에 작성한 ImageService.javaS3Uploader.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가 생성된다.

포스트맨 테스트

스크린샷 2022-08-25 오전 12 08 01

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

스크린샷 2022-08-25 오전 12 08 25
AWS S3에 다음과 같이 두 개의 파일이 올라간 것을 확인할 수 있다.

스크린샷 2022-08-25 오전 12 09 28

또한, mysql db의 Image 테이블에도 두 개의 컬럼이 추가되었음을 확인할 수 있다!😃

Ref.



💛 개인 공부 기록용 블로그입니다. 👻

맨 위로 이동하기

태그:

카테고리:

업데이트: