Issue
I have a spring boot application with rest controller that has to accept binary stream at post endpoint and do the things with it.
So i have:
@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public String parse(RequestEntity<InputStream> entity) {
return service.parse(entity.getBody());
}
When i try to test it with MockMvc i get org.springframework.web.HttpMediaTypeNotSupportedException. I see in log: Request:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /parse
Parameters = {}
Headers = [Content-Type:"application/octet-stream;charset=UTF-8", Content-Length:"2449"]
Body = ...skipped unreadable binary data...
Session Attrs = {}
Response:
MockHttpServletResponse:
Status = 415
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Accept:"application/json, application/*+json", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I tried to add explicit header:
@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE},
headers = "Accept=application/octet-stream")
Does not help. The testing call is:
mvc.perform(post("/parse")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.content(bytes)
).andDo(print())
.andExpect(status().isOk());
How can i make it work without going to multipart-form?
Solution
I have analysed this issue and got to know that issue is in this method.
@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public String parse(RequestEntity<InputStream> entity) {
return service.parse(entity.getBody());
}
Here method parameter is of type RequestEntity<InputStream>
it should be HttpServletRequest
So here is the fix.
@PostMapping(value = "/upload",
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public String demo(HttpServletRequest httpServletRequest) {
ServletInputStream inputStream;
try {
inputStream = httpServletRequest.getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
final List<String> list = new BufferedReader(new InputStreamReader(inputStream))
.lines().toList();
System.out.println(list);
return "Hello World";
}
Test Case
@Autowired
private MockMvc mockMvc;
@Test
public void shouldTestBinaryFileUpload() throws Exception {
mockMvc
.perform(MockMvcRequestBuilders
.post("/upload")
.content("Hello".getBytes())
.contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(MockMvcResultMatchers
.status()
.isOk())
.andExpect(MockMvcResultMatchers
.content()
.bytes("Hello World".getBytes()));
}
Answered By - Rohit Agarwal
Answer Checked By - Marilyn (JavaFixing Volunteer)