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
相关产品推荐
相关产品推荐

