TIL

[TIL - 20230513] 게시글 수정(썸네일 변경 포함)을 위한 MutipartFile과 Dto 함께 받기

Chef.Yeon 2023. 5. 14. 04:21

 

💻문제점

게시글 작성과 이미지 업로드를 위해 MultipartFile과 dto를 함께 받아야할 일이 생겼다. @RequestBody와 @RequestParam을 사용해서 데이터를 받으려고 했다. 하지만 실패!

public ResponseDto<?> updatePostStory(@PathVariable Long id,
                                      @Valid @RequestBody PostInfoRequestDto postInfoRequestDto,
                                      @RequestParam(value="ghumbnail") MultipartFile image) {
    return postService.updatePostInfo(id, postStoryRequestDto, image);
}

📃시도

1. PostInfoRequestDto 클래스에 MultipartFile 프로퍼티 추가하여 @ModelAttribute 애노테이션을 사용했다.

public ResponseDto<?> updatePostStory(@PathVariable Long id,
                                      @ModelAttribute PostInfoRequestDto postInfoRequestDto) {
    return postService.updatePostInfo(id, postStoryRequestDto, image);
}
@Getter
public class PostInfoRequestDto {
    @Size(max = 40, message = "{title}")
    @NotBlank
    private String title;

    @Size(min = 500000, max = 100000000, message = "{targetAmount}")
    private int targetAmount;

    @Size(min = 1000, message = "{price}")
    private int price;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
    @Future(message = "{future}")
    private LocalDate deadLine;

    private List<String> searchTag = new ArrayList<>();

    private MultipartFile thumbnail;
}

 

포스트맨에서 다음과 같이 요청했다.

 

오류가 안 나길래 되는줄 알았는데, 확인해보니 값들이 변경되지 않고 null이다...


🔍해결

@RequestPart 애노테이션을 사용했다. key가 postInfo이고 value는 PostInfoRequestDto 클래스에 해당하는 Json이 들어가게 된다.

@PutMapping(value = "/{id}/info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseDto<?> updatePostIndo(@PathVariable Long id,
                                     @Valid @RequestPart(value = "postInfo") PostInfoRequestDto postInfoRequestDto,
                                     @RequestPart(value="thumbnail", required = false) MultipartFile multipartFile) {
    return postService.updatePostInfo(id, postInfoRequestDto, multipartFile);
}

 

@Getter
public class PostInfoRequestDto {
    @Size(max = 40, message = "{title}")
    @NotBlank
    private String title;

    @Size(min = 500000, max = 100000000, message = "{targetAmount}")
    private int targetAmount;

    @Size(min = 1000, message = "{price}")
    private int price;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
    @Future(message = "{future}")
    private LocalDate deadLine;

    private List<String> searchTag = new ArrayList<>();
}

 

다음과 같이 dto 클래스에 맞는 Json 데이터를 value로 가지고 있다.

 

DB도 확인해 봤더니, 정상적으로 반영되었고, S3에도 이미지가 업로드 되었다.

 

프론트에서 요청은 다음과 같이 했다.

  const onClickSaveStory = async (event) => {
    event.preventDefault();
    const formData = new FormData();

    const storyData = {
      summary: summary,
      storyBoard: storyBoard,
    };

    formData.append("projectImage", file); // assuming selectedFile is your file input

    formData.append(
      "postStory",
      new Blob([JSON.stringify(storyData)], {
        type: "application/json",
      })
    );
    try {
      await jwtInstance.put(`/posts/${id}/story`, formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });
    } catch (error) {
      console.error(error);
    }
  };

 

https://yeon-dev.tistory.com/188

 

[Spring] @RequestPart 사용하여 MultipartFile과 Dto 함께 받기, Postman 테스트

글을 작성한다고 할때, 제목, 내용을 작성할 수 있다면 다음과 같이 Controller와 dto클래스를 작성할 수 있을 것이다. @PostMapping("/post") public ResponseDto savePost(@Valid @RequestBody PostRequestDto postRequestDto, @Au

yeon-dev.tistory.com

 

728x90