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

Spring Cloud Contract:Groovy DSL如何指定Multipart请求Part的Content-Type

解决Spring Cloud Contract处理multipart/mixed请求的Content-Type指定问题

我之前也碰到过这个问题!当用Spring Cloud Contract处理带多个@RequestPart的multipart请求时,默认的Groovy DSL写法确实不会自动给每个Part指定Content-Type,得手动在契约里配置每个Part的请求头才行。

针对你的控制器方法,这里给出正确的Groovy DSL契约写法,能精准指定每个请求Part的Content-Type:

Contract.make {
    request {
        method POST()
        url "/posts"
        multipart(
            // 配置header文件Part,指定Content-Type为对应文件类型(这里用image/jpeg举例)
            header: named(
                content(file("header.jpg")),
                headers: [
                    "Content-Type": "image/jpeg",
                    "Content-Disposition": "form-data; name=header; filename=header.jpg"
                ]
            ),
            // 配置photo文件Part
            photo: named(
                content(file("photo.png")),
                headers: [
                    "Content-Type": "image/png",
                    "Content-Disposition": "form-data; name=photo; filename=photo.png"
                ]
            ),
            // 配置info的JSON Part,指定Content-Type为application/json
            info: named(
                content('{"title": "Test Post", "content": "Hello World"}'),
                headers: [
                    "Content-Type": "application/json",
                    "Content-Disposition": "form-data; name=info"
                ]
            )
        )
    }
    response {
        status OK()
        body('"ok"')
        headers {
            contentType applicationJson()
        }
    }
}

关键细节说明:

  • 用multipart块包裹所有请求Part,每个Part通过named方法来定义,这样就能为单个Part单独设置请求头(包括Content-Type)。
  • 对于文件类型的Part(header和photo):
    • 用file("xxx")指定测试用的文件,这个文件要放在和契约文件同级的目录下(比如契约在src/test/resources/contracts/posts,文件也要放在这里)。
    • 必须设置Content-Disposition头,其中name要和控制器@RequestPart的参数名完全一致,filename是上传时的文件名。
  • 对于JSON类型的info Part:
    • 直接传入符合格式的JSON字符串作为content,然后指定Content-Type为application/json,同样要保证Content-Disposition的name和参数名一致。

生成的测试代码效果

配置完成后,自动生成的MockMvc测试代码会正确为每个Part设置Content-Type,大概长这样:

// given:
MockMvcRequestSpecification request = given()
    .header("Content-Type", "multipart/mixed")
    .multiPart("header", "header.jpg", resourceLoader.getResource("classpath:contracts/posts/header.jpg").getInputStream(), "image/jpeg")
    .multiPart("photo", "photo.png", resourceLoader.getResource("classpath:contracts/posts/photo.png").getInputStream(), "image/png")
    .multiPart("info", "{\"title\": \"Test Post\", \"content\": \"Hello World\"}", "application/json");

// when:
ResponseOptions response = given().spec(request).post("/posts");

// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).isEqualTo("application/json");
assertThat(response.body().asString()).isEqualTo("\"ok\"");

额外注意事项

  • 确保测试文件存在于正确路径,否则生成的测试会因找不到文件报错。
  • 如果你的Json是自定义类型,要保证契约里的JSON字符串能被正确反序列化为该类型。
  • Content-Disposition的name必须和控制器方法的@RequestPart参数名严格匹配,否则Spring无法正确绑定参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:17:21