Rest Assured上传.gz文件报400 Bad Request问题求助
问题概述
使用Rest Assured 5.5.0上传.gz格式文件,尝试multipart/form-data和直接二进制请求体两种方式均返回400 Bad Request - Request Badly formed,参考Swagger提供的Curl命令仍未解决。
核心问题排查与修正步骤
1. 移除冲突的请求体配置
代码同时使用了.body(gzFile)和.multiPart("File", gzFile, "application/x-gzip"),这会导致请求体结构混乱。multipart/form-data请求不需要手动设置body,Rest Assured会通过multiPart自动构建正确的请求体结构。
2. 删除冗余无效的请求头
代码中添加的header("multipart-form-data","multipart/form-data")是无效头(Curl里的这行也是错误的),直接删除即可。此外,手动设置Content-Type: multipart/form-data会丢失框架自动生成的boundary参数,这是multipart请求的必要组成部分。
3. 修正Accept-Encoding头的误用
Accept-Encoding: application/gzip是告诉服务器响应可以用gzip压缩,不是标识请求体的压缩格式。如果服务器要求请求体是gzip压缩的,应该使用Content-Encoding: gzip头;如果只是上传.gz文件,这个头可以直接移除。
4. 正确设置Multipart请求的ContentType
改用Rest Assured内置的contentType(ContentType.MULTIPART),框架会自动添加包含boundary的正确Content-Type头,避免手动设置导致的格式错误。
5. 验证文件路径与存在性
确保代码中构建的文件路径指向真实存在的文件,可添加文件存在性校验:
if (!gzFile.exists() || !gzFile.isFile()) { throw new IllegalArgumentException("File not found or is not a file: " + gzFile.getAbsolutePath()); }
6. 匹配Swagger定义的请求格式
Swagger中文件上传定义为string($binary),说明服务器可能接受两种格式:
- Multipart方式:对应Curl的
-F参数 - 直接二进制请求体:将.gz文件的二进制内容作为请求体,不需要multipart结构
修正后的代码示例
示例1:Multipart/form-data方式
String token = "Bearer eyJhbGcioiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUHTN"; File gzFile = new File(System.getProperty("user.dir") + "/abcDataUpdated.json.gz"); // 校验文件存在性 if (!gzFile.exists()) { throw new RuntimeException("Target file not found: " + gzFile.getAbsolutePath()); } RestAssured.useRelaxedHTTPSValidation(); Response response = given() .log().all() .contentType(ContentType.MULTIPART) .header("accept", "application/json") .header("Correlation-Request-Id", "12345") // 和Curl保持一致 .header("Authorization", token) .multiPart("File", gzFile, "application/x-gzip") .post("https://serverip:port/testingapi/abc") .then() .log().all() .extract().response();
示例2:直接二进制请求体方式(适配Swagger的string($binary)定义)
String token = "Bearer eyJhbGcioiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUHTN"; File gzFile = new File(System.getProperty("user.dir") + "/abcDataUpdated.json.gz"); if (!gzFile.exists()) { throw new RuntimeException("Target file not found: " + gzFile.getAbsolutePath()); } RestAssured.useRelaxedHTTPSValidation(); Response response = given() .log().all() .contentType("application/x-gzip") .header("accept", "application/json") .header("Correlation-Request-Id", "12345") .header("Authorization", token) .body(gzFile) .post("https://serverip:port/testingapi/abc") .then() .log().all() .extract().response();
额外排查点
- 检查
Authorizationtoken的有效性:确保token未过期、权限足够 - 对比Curl和Rest Assured的请求日志:用抓包工具对比两者的请求头、请求体结构差异,重点看
Content-Type是否包含boundary、请求体的编码格式 - 验证服务器端的文件接收逻辑:确认服务器是否要求特定的文件名、文件大小限制,或者是否对gzip文件的内容格式有要求(比如内部必须是有效的JSON)
内容的提问来源于stack exchange,提问作者Cyril Thomas

