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

Kotlin下Retrofit2提交含double、字符串、图片的multipart请求报400如何解决

问题核心原因

Multipart/form-data 请求中所有非文件的普通参数,无论类型是字符串还是数字,都需要封装为text/plain类型的RequestBody才能被服务端正确解析。你当前直接将Double类型的数值传入@Part参数,Retrofit 无法将其序列化为 form-data 要求的文本格式,同时文件参数直接使用RequestBody也会缺少必要的文件名头信息,两个问题共同导致了400错误。


解决方案

第一步:修改API接口定义

将数字类型参数改为RequestBody类型,同时文件参数改用MultipartBody.Part适配后端文件字段校验规则:

interface IReportAPI {
    @Multipart
    @POST("/api/Reports")
    suspend fun postReport(
        @Header("Authorization") token: String,
        @Part("AssignmentId") assignmentId: RequestBody?,
        @Part("MachineId") machineId: RequestBody?,
        @Part("Distance") distance: RequestBody?,
        @Part("OriginalDistance") originalDistance: RequestBody?,
        @Part("WorkedHours") workedHours: RequestBody?,
        @Part("OriginalWorkedHours") originalWorkedHours: RequestBody?,
        @Part routeImageFormFile: MultipartBody.Part?
    ): JsonObject
}

第二步:修改业务调用代码

将Double数值转为RequestBody,同时把文件封装为MultipartBody.Part:

val assignmentID: RequestBody = RequestBody.create(
    MediaType.parse("text/plain"),
    "79087c01-573a-a727-028d-d667bd54e236"
)

val machineID: RequestBody = RequestBody.create(
    MediaType.parse("text/plain"),
    "39077c01-59a3-bc5a-8563-e9d63f1027d1"
)

// Double数值转RequestBody
val distance = RequestBody.create(MediaType.parse("text/plain"), 10.0.toString())
val originalDistance = RequestBody.create(MediaType.parse("text/plain"), 11.0.toString())
val workedHours = RequestBody.create(MediaType.parse("text/plain"), 12.0.toString())
val originalWorkedHours = RequestBody.create(MediaType.parse("text/plain"), 13.0.toString())

// 封装文件为MultipartBody.Part
val fileUri = Uri.parse("android.resource://fi.gambitlabs.puhasworker/drawable/drawer_picture.png")
val imgFile = File(fileUri.path)
val fileRequestBody: RequestBody = RequestBody.create(MediaType.parse("image/*"), imgFile)
val routeImagePart = MultipartBody.Part.createFormData("RouteImageFormFile", imgFile.name, fileRequestBody)

// 发起请求
message = reportService.postReport(
    authService.getAuth(token),
    assignmentID,
    machineID,
    distance,
    originalDistance,
    workedHours,
    originalWorkedHours,
    routeImagePart
)

新版OkHttp适配说明

如果你的项目依赖OkHttp 4及以上版本,废弃的create方法可以用更简洁的扩展方法替代:

  • 普通参数:"10.0".toRequestBody("text/plain".toMediaType())
  • 文件参数:imgFile.asRequestBody("image/*".toMediaType())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:36:04