OpenAPI Generator客户端MultiPartFile与Resource类型兼容问题
OpenAPI Generator生成的文件上传客户端与服务端不兼容,报错"Required part 'file' is not present"
OpenAPI定义
服务端接口定义
summary: Upload document API call operationId: upload requestBody: content: multipart/form-data: schema: $ref: 'requests/document-upload.yaml#/DocumentUploadRequestDto'
请求体DTO定义
DocumentUploadRequestDto: type: object properties: customer: type: string description: 上传文档所属的客户标识 nullable: false user: type: string description: 上传文档的用户标识 nullable: false file: type: string format: binary description: 待上传的文档文件 nullable: false required: - customer - user - file
Spring生成器生成的服务端代码(运行正常)
public ResponseEntity<DocumentUploadResponseDto> upload(String customer, String user, MultipartFile file) { return ResponseEntity.ok(service.upload(customer, user, file)); }
Java生成器生成的客户端配置与代码
Gradle生成任务配置
tasks.register('openApiGenerateClient', GenerateTask) { group = 'openapi tools' description = "Generate blocking Spring client side code for the ${StringUtils.capitalize(project.name)} API" generatorName = "java" inputSpec = "$projectDir/src/main/resources/openapi/${project.name}.yaml" as String outputDir = layout.buildDirectory.dir("generated/client").map { it.asFile.toPath().toString() } invokerPackage = "com.test.test.document" apiPackage = "com.test.test.document.client" modelPackage = "com.test.test.document.model" modelFilesConstrainedTo = [] configOptions = [ dateLibrary : 'java8', serializationLibrary : 'jackson', library : 'resttemplate', useBeanValidation : "false", interfaceOnly : "true", serializableModel : "true", useTags : "true", sourceFolder : 'src/main/java', testFolder : 'src/test/java', artifactId : "${project.name}-client", artifactVersion : "$projectVersion", groupId : 'com.test.test', performBeanValidation : 'false', snapshotVersion : System.getenv("IS_RELEASE") ? 'false' : 'true', useAbstractionForFiles: 'true', useJakartaEe : 'true' ] typeMappings = [ 'File': 'org.springframework.core.io.Resource' ] }
生成的客户端方法
public DocumentUploadResponseDto upload(String customer, String user, org.springframework.core.io.Resource _file) throws RestClientException { return uploadWithHttpInfo(customer, user, _file).getBody(); }
客户端调用逻辑
尝试将服务端接收的MultipartFile转为InputStreamResource传入客户端:
@Override public DocumentUploadResponseDto upload(String customer, String user, MultipartFile file) { try { return mapper.convert(client.upload(customer, user, new InputStreamResource(file.getInputStream()))); } catch (IOException e) { log.error("An error has occurred while proxying an upload document request file", e); throw new RuntimeException(e); } }
报错信息
调用后下游服务抛出异常:
2024-08-30T00:09:19.115+03:00 ERROR 34521 --- [document-service] [omcat-handler-6] c.a.p.d.e.ApplicationExceptionHandler : A generic exception has occurred! Message is Required part 'file' is not present. org.springframework.web.multipart.support.MissingServletRequestPartException: Required part 'file' is not present. at org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver.resolveArgument(RequestPartMethodArgumentResolver.java:168) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) ~[spring-web-6.1.12.jar:6.1.12] at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:224) ~[spring-web-6.1.12.jar:6.1.12] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:178) ~[spring-web-6.1.12.jar:6.1.12] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.12.jar:6.1.12] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.12.jar:6.1.12] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.28.jar:6.0] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.12.jar:6.1.12] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.28.jar:6.0] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.28.jar:10.1.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.28.jar:10.1.28] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.28.jar:10.1.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.28.jar:10.1.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.28.jar:10.1.28] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.12.jar:6.1.12]
疑问与需求
- 明明已经传入file参数,却抛出
MissingServletRequestPartException异常,原因不明 - 客户端将file参数生成为
Resource类型,而非服务端匹配的MultipartFile,不理解此生成逻辑 - 需要解决上述问题,生成与服务端兼容、可正常工作的客户端
内容的提问来源于stack exchange,提问作者vkourt
相关产品推荐
相关产品推荐

