본문 바로가기
공부/Spring

[Spring] JSON과 같이 이미지 요청 받아서 저장

by 웅대 2023. 2. 6.
728x90
반응형

간단한 게시판을 만드던 중 이미지 업로드하는 기능이 필요해서 만들어보았다.

1. 이미지 이름

이미지를 보내서 저장할 때는 이미지의 이름이 중요하다.

 

같은 이름을 가진 이미지를 전송할 경우 충돌이 일어나기 때문이다.

 

그래서 같은 이름을 가지더라도 서로 구분할 수 있도록 문자열을 붙여준다.

UUID.randomUUID().toString()로 랜덤한 uuid를 생성하여 붙여준다.
private static String changedImageName(String originName) {
    String random = UUID.randomUUID().toString();
    return random+originName;
}

2. 이미지 클래스

@AllArgsConstructor
@Getter
public class Image {
    //요청을 하면 클라이언트에게 originName을 보여주고
    //storedImagePath에 저장된 경로에서 불러오면 됨
    private String originName;
    private String storedImagePath;
}

위에서 새로운 이미지 이름을 생성했다.

 

그래도 원래의 이미지 이름이 필요할 수 있으므로 새로 만든 이미지 이름과 같이 보관을 하기 위해서 Image 클래스를 생성했다.

 

2. 저장될 이미지의 경로

이미지의 주소를 상대 경로로 정할수도 있고 절대 경로로 정할수도 있다.
나는 일단 업로드한 이미지를 로컬에 저장하는 것이 목표라서 c드라이브 아래에 images 폴더를 생성하여 절대 경로로 이 위치를 지정했다.
private static String createDirPath(String changedName) {

    return "c:\\images\\"+changedName;
    //이미지가 저장될 경로. 필요에 따라 경로 조정
}

3. 이미지 업로드

public static Image uploadImage(MultipartFile image) {
    String originName = image.getOriginalFilename();
    String changedName = changedImageName(originName);
    String storedImagePath = createDirPath(changedName);
    System.out.println("storedImagePath = " + storedImagePath);

    try {
        image.transferTo(new File(storedImagePath));
    } catch (IOException e){
        throw new ImageUploadException();
        //내가 만든 커스텀 예외.
        //직접 만든 예외라서 적절히 변경하여 사용.

    }
    return new Image(originName, storedImagePath);
}

이미지는 MultipartFile 타입으로 받게 되는데 이 타입의 getOriginalFilename 메소드를 사용하여 원래 이미지 이름을 얻을 수 있다.

 

이를 사용하여 새롭게 이름을 만들고 경로를 만든다.

 

그리고 이미지를 저장하기 위해서 MultipartFile의 transferTo 메소드를 사용한다.

 

인자로 넣어둔 경로로 이미지가 저장된다.

 

또한 예외가 발생하면 커스텀 예외를 던져준다. 이는 @RestControllerAdvice 어노테이션이 달린 곳에서 처리하도록 하였다.

 

(@RestControllerAdvice 참고)

https://growth-coder.tistory.com/101

 

깃헙 참고 : https://github.com/ezcolin2/Spring-Class/tree/main/image%20upload

 


JSON 파일과 함께 이미지 파일 받기

 

이미지 파일만 받는다면 보통 @RequestParam 어노테이션을 사용해서 받는다.

 

그런데 나는 게시글을 올릴 때 게시글의 정보와 함께 이미지를 넘겨주고 싶었다.

 

이럴 때는 @RequestPart 어노테이션을 사용한다.

 

먼저 @RequestPartm 어노테이션을 사용한 컨트롤러의 모습은 아래와 같다.

@PostMapping("")
public ResponseEntity<JsonResponse> registerPost(
        @RequestPart(value="post", required = true) PostDto post,
        @RequestPart(value="image", required = true) MultipartFile image
        ) {
    postService.registerPost(post, image);
    JsonResponse response = JsonResponse.builder()
            .code(HttpStatus.OK.value())
            .httpStatus(HttpStatus.OK)
            .message("게시글 등록 성공").build();
    return new ResponseEntity<>(response, response.getHttpStatus());
}

@RequestPartm 두번째 인자로 required=true가 들어가있는데 이는 default 값이라서 굳이 안적어도 된다.

 

나는 이미지를 반드시 첨부해야 글이 등록되도록 만들 예정이라 true로 두었는데 그렇지 않아도 된다면 false로 두고 따로 null 처리를 해줘야한다.

 

@RequestParam을 활용한 형태는 form-data 형태로 넘겨줘야한다.

 

postman 기준으로 key-value 쌍으로 넘겨주게된다.

post라는 key에 해당하는 VALUE는 길어서 생략되었는데 아래와 같다.

{
    "postTitle" : "테스트 제목",
    "writerId" : "테스트 유저",
    "time" : "2022-01-25",
    "content" : "안녕하세요 신입입니다."
}

이러한 JSON 형식은 꼭 content type에 application/json을 적어줘야한다.

그리고 포스트맨은 기본적으로 text로 설정되어있는데 파일을 넣고 싶으면 위 사진처럼 Text에서 File로 변경해야한다.

 

기본적인 이미지 업로드 방식에 대해 알고싶어서 정말 간단하게 구현해보았다.

 

부족한 점이 많이 보이지 프로젝트를 조금 더 진행하면서 보완해나갈 예정이다.

728x90
반응형

댓글