不能让RestController接受应用程序/八位字节流



我有一个带有rest控制器的spring-boot应用程序,它必须在后端接受二进制流并用它做事情。

所以我有:

@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public String parse(RequestEntity<InputStream> entity) {
return service.parse(entity.getBody());
}

当我尝试用MockMvc测试它时,我得到了org.springframework.web.HttpMediaTypeNotSupportedException。我在日志中看到:请求:

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 = {}

响应:

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 = []

我试图添加明确的标题:

@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE},
headers = "Accept=application/octet-stream")

没有帮助。测试调用是:

mvc.perform(post("/parse")                       
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.content(bytes)
).andDo(print())
.andExpect(status().isOk());

如果不使用多部分形式,我如何使其工作?

我已经分析了这个问题,并知道这个问题存在于这个方法中。

@PostMapping(path="/parse", consumes = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public String parse(RequestEntity<InputStream> entity) {
return service.parse(entity.getBody());
}

这里的方法参数是类型RequestEntity<InputStream>,它应该是HttpServletRequest

所以这里是解决办法。

@PostMapping(value = "/upload",
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public String demo(HttpServletRequest httpServletRequest) {
try (ServletInputStream inputStream = httpServletRequest.getInputStream()) {
new BufferedReader(new InputStreamReader(inputStream, UTF_8))
.lines().forEach(System.out::println);
} catch (IOException e) {
throw new RuntimeException(e);
}
return "Hello World";
}

测试用例

@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()));
}

最新更新