클라이언트로부터 HTTP를 통해 이미지 데이터를 multipart/form-data로 받아오며, @RequestParam("")을 통해 MultipartFile로 binding
하는 과정에서 데이터를 받아오지 못해 Null값이 저장되는 상황에 직면했습니다.
2023-04-16 13:24:03.448 WARN 14798 --- [http-nio-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'image' is not present]
이를 해결하기위한 오류 해결기를 작성해보려합니다.
각 어노테이션에 따라 binding 될 수 있는 타입이 다릅니다.
이중에서 multipart/form-data를 바인딩 할 수 있는 어노테이션을 골라야 합니다.
하지만 이를 통해 해결하진 못했습니다.
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
MultipartResolver를 새로운 구현체로 바꾸는 작업입니다.
Common, Standard 2가지를 다 진행해도 오류는 여전히 나아지지 않았습니다.
에초에 MultipartFile 객체는 직접 Controller 메서드에서 바인딩 해야하기 때문에 Dto로 설정할 수 없습니다.
POST를 했을 때, Spring MVC의 multipartFile 객체로의 충돌 때문에 제대로 바인딩이 되지 못할 수 있다고 생각했습니다.
이에 axios 대신 AJAX를 사용하는 방안을 모색했습니다.
stackoverflow의 여러 포스팅에서 해결 코드를 분석했을 때, 공통적으로 각 Formdata 안에 type과 name을 명시했었습니다.
예상하기론, 데이터를 객체로 역직렬화하기위한 바인딩 과정에서 어떤 이름을 가진 데이터를 바인딩 해야할 지 몰라서 null로 리턴되는 문제라고 생각합니다.
이를 확실히 명시해주기 위해서는 다음과 같이 각 header, payload 쌍에 필요합니다.
Content-Type
Content-Deposition
다음은 postman에서 POST 요청 했을 때 wireshark을 이용해서 캡쳐한 요청 헤더의 일부분입니다.
Content-Type: image/png\r\n\r\n
Content-Disposition: form-data; name="image"; filename="spring.png"\r\n
이렇게 각 페이로드 단에 2개의 헤더를 붙입니다.
이틀 꼬박 밤샘한 결과입니다.
결론은 React에서 <input>
태그를 사용하는 것으로 해결했습니다.
Spring Boot multipart upload getting null file object
Spring Boot multipartfile always null
Issue with MultipartFile Upload From React/Node
multipart/form-data binding for ModelAttribute fails if multipart file param is null
MultipartFile 인자로 받을 때 null 되는 현상
multipart/form-data 타입의 HTTP 메시지 구성 방법
Content-Disposition