使用Apache HttpClient向Spring Boot上传Multipart文件遇415错误
问题详情
Spring Boot应用的文件上传端点代码如下:
@PostMapping("/") public ResponseEntity<FileUploadResponseDto> upload(@RequestPart("details") FileUploadDto fileUploadDto,@RequestParam("file") MultipartFile file){ try { return ResponseEntity.ok( fileUploadService.uploadFile(fileUploadDto,file)); }catch (Exception e){ return ResponseEntity.status(406).body(new FileUploadResponseDto(false,e.getMessage())); } };
使用Postman测试该接口一切正常,但通过Apache HttpClient调用时,Spring Boot返回application/octet-stream is not supported错误,响应信息如下:
HttpResponseProxy{HTTP/1.1 415 [Accept: application/json, application/*+json, Content-Type: application/json, Transfer-Encoding: chunked, Date: Sun, 11 Feb 2024 22:02:27 GMT, Keep-Alive: timeout=60, Connection: keep-alive] ResponseEntityProxy{[Content-Type: application/json,Chunked: true]}}
对应的Apache HttpClient调用代码:
String json = mapToJson(Map.of("name",(String)file[1],"lastname", (String)file[2],"createTime",(String)file[3])); final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.addTextBody("details",json,ContentType.APPLICATION_JSON); builder.addBinaryBody("file",(File)file[4],ContentType.APPLICATION_OCTET_STREAM,((File)file[4]).getName()); final HttpPost httpPost = new HttpPost("http://"+host+":"+port+"/api/v1/upload/"); try(CloseableHttpClient client = HttpClientBuilder.create().build()) { final HttpEntity entity = builder.build(); httpPost.setEntity(entity); HttpResponse httpResponse = client.execute(httpPost); System.out.println(httpResponse); } catch (IOException e) { throw new RuntimeException(e); }
解决方案
原本代码中设置了builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);,调试发现Spring端接收的请求存在异常——details部分的content-type为null,导致Spring无法正确识别该部分的JSON类型,从而抛出不支持的媒体类型错误。
将Multipart模式切换为builder.setMode(HttpMultipartMode.STRICT);后,request.getParts()中的details部分会正确携带application/json类型标识,Spring能够正常解析请求,问题解决。
内容的提问来源于stack exchange,提问作者Filip Cacic

