You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:55:55