Vue + Spring Boot으로 파일과 DTO 함께 REST 통신하기

Spring Boot Controller 부분

@PostMapping(value = "", consumes = {"multipart/form-data"})
public ResponseEntity<? extends BaseResponseBody> createRoom(
        @RequestPart(value = "thumbnail", required = false) MultipartFile thumbnail,
        @RequestPart(value = "room", required = true) RoomCreatePostReq req) {

    ...
}
  • @PostMapping 어노테이션 인자 중 consumes{"multipart/form-data"}로 설정
  • file(MultipartFile)과 DTO를 인자로 받기 위해 @RequestPart 어노테이션 사용
  • 이때 프론트에서 FormData() 객체 보내줄 때 key로 @RequestPart에서 설정한 value를 잘 설정해야함

Vue Axios 부분

const createRoom = () => {
  var thumbnailImg = document.getElementById("thumbnail").files[0]
  const room = {
    capacity: state.capacity,
    description: state.description,
    password: state.password,
    title: state.title,
  }
  
  const roomData = new FormData()
  roomData.append("thumbnail", thumbnailImg)
  roomData.append("room", new Blob([JSON.stringify(room)] , {type: "application/json"}))

  store.dispatch('root/createRoom', roomData)
  .then(() => {
    console.log('요청은 성공')
    // router.push({ name: 'ConferenceDetail' })
  })
  .catch((err) => {
    console.log('실패')
    console.log(err)
  })
}
  • file을 받는 input 태그 자체를 getElementById()로 받아와서 파일 배열의 첫번째 파일로 인덱싱하고 이를 파일 변수로 저장
  • room 객체는 new Blob()안에 JSON.stringify()을 통해 JSON 형식으로 변환한 뒤, type을 application/json 으로 설정
  • FormData() 객체에 file과 room 을 백엔드 @RequestPart에서 설정한 value를 잘!! 설정하고 append 해야함
  • store.dispatch(‘root/createRoom’, roomData) 에서 두번째 매개변수로 FormData 객체 넘겨줄 때 { } 로 감싸지 말고 자기 자신을 그대로 넘겨줘야함
  • axios 보낼 때 header에 ‘Content-Type’:‘multipart/form-data’로 설정