What
@RequestPart 는 Multipart 요청을 인자로 받을 수 있도록 하는 애노테이션이다.
해당 애노테이션을 사용하면 Json, XML과 같은 payload와 함께 Multipart 인자를 처리할 수 있다.
이외에 멀티파트 인자와 함께 처리할 수 있는 애노테이션은 @ModelAttribute 애노테이션으로 처리할 수있다.
여기이서는 POJO인 Employee 객체안에 Multipart type 을 받고 있다.
public class Employee { private String name; private MultipartFile document; } ------- boundary --------- @RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) public String saveEmployee(@ModelAttribute Employee employee) { employeeService.save(employee); return "employee/success"; }
또 한가지 @ReuqestParm으로 도 처리할 수 있다.
@RequestMapping(path = "/requestparam/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) public ResponseEntity<Object> saveEmployee(@RequestParam String name, @RequestPart MultipartFile document) { Employee employee = new Employee(name, document); employeeService.save(employee); return ResponseEntity.ok().build(); }
How
POSTMAN 에서 MultipartType과 JSON 데이터 보내는 예제

일반적인 예제 테스트 코드에서는 이렇게 나와있다.
// @RequestParam, ModelAttribte 테스트 @Test public void givenRequestPartAndRequestParam_whenPost_thenReturns200OK() throws Exception { mockMvc.perform( multipart("/requestparam/employee") // mulipart uri .file(A_FILE) .param("name", "testname")) .andExpect(status().isOk()); } // @RequestPart 테스트 @Test public void givenEmployeeJsonAndMultipartFile_whenPostWithRequestPart_thenReturnsOK() throws Exception { MockMultipartFile employeeJson = new MockMultipartFile("employee", null, "application/json", "{\"name\": \"Emp Name\"}".getBytes()); mockMvc.perform(multipart("/requestpart/employee") .file(A_FILE) .file(employeeJson)) .andExpect(status().isOk()); }
RequestPart 애노테이션은 default 속성으로 무조건 해당 매개변수가 존재해야 한다.
해당 값이 없으면 required 해야한다는 문구가 보일 것이다.
해당 예제처럼 글로 파싱하는 불필요한 작업 없이 ObjectMapper로 가능한지 테스트 해본 결과 성공했다.
- json valute를 byte로 변경하고 RequestPart이니 part라는 메소드를 이용하여 요청해봤다.
- part는 requestparam 형식과 똑같은 메소드였다. 그래서 해당 예외가 출력됬다.
→ Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
json byte로 요청한 것은 ‘octet-stream' 인식하고 RequestParam으로 담기게 된다.
@Test void create() throws Exception { Resource resource = resourceLoader.getResource("classpath:/static/" + "test.png"); CreateReviewRequestDto createReviewRequestDto = new CreateReviewRequestDto(1L, 3, ""); // byte stream이니깐 'application/octet-stream' 으로 컨텐츠 인식함. ResultActions perform = mockMvc.perform( multipart(URI_PREFIX) .file((MockMultipartFile)mockfile) .part(new MockPart("createReviewRequest",objectMapper.writeValueAsBytes(createReviewRequestDto))) .contentType(MediaType.MULTIPART_FORM_DATA_VALUE) ); perform.andExpect(status().isOk()); }
구체적 예외
MockHttpServletRequest: HTTP Method = POST Request URI = /api/reviews Parameters = {createReviewRequest=[{"orderProductId":1,"score":3,"contents":""}]} Headers = [Content-Type:"multipart/form-data;charset=UTF-8"] Body = null Session Attrs = {} Handler: Type = com.platform.order.review.controller.ReviewController Method = com.platform.order.review.controller.ReviewController#create(JwtAuthentication, CreateReviewRequestDto, List) Async: Async started = false Async result = null Resolved Exception: Type = org.springframework.web.HttpMediaTypeNotSupportedException
- 이번엔 MultipartFile에 매개변수 명과 미디어 타입을 JSON으로 변경하고 dto를 바이트 코드로 변환했더니 성공했다.
@Test void create() throws Exception { Resource resource = resourceLoader.getResource("classpath:/static/" + "test.png"); CreateReviewRequestDto createReviewRequestDto = new CreateReviewRequestDto(1L, 3, ""); // byte stream이니깐 'application/octet-stream' 으로 컨텐츠 인식함. ResultActions perform = mockMvc.perform( multipart(URI_PREFIX) .file((MockMultipartFile)mockfile) .file( new MockMultipartFile( "createReviewRequest", "", MediaType.APPLICATION_JSON_VALUE, objectMapper.writeValueAsBytes(createReviewRequestDto)) ) .contentType(MediaType.MULTIPART_FORM_DATA_VALUE) ); perform.andExpect(status().isOk()); } ================================================================================= MockHttpServletRequest: HTTP Method = POST Request URI = /api/reviews Parameters = {} Headers = [Content-Type:"multipart/form-data;charset=UTF-8"] Body = null Session Attrs = {}