我有一个带有休息控制器的 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()));
}
我遇到了同样的错误,并通过添加 mvc 配置中缺少的 ocet 流转换器来修复它。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
convertes.add(new ByteArrayHttpMessageConverter());
}
}