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

Spring OpenAPI生成客户端:无filename的MultipartFile接收异常问题

问题描述

我用OpenAPI生成的Spring客户端处理MultipartFile对象,大部分场景运行正常,但调用接口时,若Content-Disposition头缺少filename属性,请求就会失败;只要添加filename属性(哪怕值为空),请求就能正常执行。

错误请求头示例:

Content-Disposition: form-data; name="file"

正常请求头示例:

Content-Disposition: form-data; name="file"; filename=

由于需要在单次请求中同时上传文件及附加元数据,必须依赖multipart方式,无法更换上传方式。请问需调整哪些配置?或该场景是否不被支持?

解决方案

1. 调整OpenAPI配置文件

在OpenAPI的yaml/json定义中,针对multipart类型的请求,给对应file参数显式指定filename为空的默认请求头:

paths:
  /upload:
    post:
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
            encoding:
              file:
                headers:
                  Content-Disposition:
                    schema:
                      type: string
                      default: "form-data; name=\"file\"; filename="

重新生成客户端代码后,请求会自动带上包含空值filename的头。

2. 自定义Spring MultipartResolver

若无法修改OpenAPI配置,可自定义Multipart解析器,允许不带filename的multipart文件项:

public class CustomMultipartResolver extends StandardServletMultipartResolver {
    @Override
    protected MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        return new CustomMultipartHttpServletRequest(request);
    }

    private static class CustomMultipartHttpServletRequest extends StandardMultipartHttpServletRequest {
        public CustomMultipartHttpServletRequest(HttpServletRequest request) throws MultipartException {
            super(request);
        }

        @Override
        protected void parseRequest(HttpServletRequest request) {
            try {
                Collection<Part> parts = request.getParts();
                for (Part part : parts) {
                    String disposition = part.getHeader(HttpHeaders.CONTENT_DISPOSITION);
                    if (disposition != null && !disposition.contains("filename=")) {
                        disposition += "; filename=";
                        // 通过反射修改Part的请求头
                        Field headersField = part.getClass().getDeclaredField("headers");
                        headersField.setAccessible(true);
                        Map<String, List<String>> headers = (Map<String, List<String>>) headersField.get(part);
                        headers.put(HttpHeaders.CONTENT_DISPOSITION, Collections.singletonList(disposition));
                    }
                }
                super.parseRequest(request);
            } catch (Exception e) {
                throw new MultipartException("解析multipart请求失败", e);
            }
        }
    }
}

然后在Spring配置中注册该解析器:

@Configuration
public class MultipartConfig {
    @Bean
    public MultipartResolver multipartResolver() {
        return new CustomMultipartResolver();
    }
}

3. 修改OpenAPI生成器模板

如果使用OpenAPI Generator的Java模板,可修改multipartForm.mustache模板,强制给file参数添加空filename的请求头:

Content-Disposition: form-data; name="{{paramName}}"; filename=

重新生成客户端代码后,所有multipart文件请求都会自动带上该头。

4. 直接修改生成的客户端代码

若上述方式都不方便,可直接修改生成的客户端代码中构建请求的逻辑,手动添加空filename的头:

// 示例:修改Multipart请求构建逻辑
MultipartBody.Builder builder = MultipartBody.builder();
// 显式指定空filename
builder.addFormDataPart("file", "", file.getInputStream(), MediaType.APPLICATION_OCTET_STREAM);
场景支持说明

该场景是被支持的,问题根源在于Spring默认的Multipart解析器要求文件类型的multipart项必须包含filename属性(即使为空),而OpenAPI生成的客户端在部分场景下未自动添加该属性。通过上述任一配置调整,均可解决问题。

内容的提问来源于stack exchange,提问作者Kaze

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:32:14