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

Android Kotlin中Retrofit如何同时传递@Part图片表单和@Query参数userId

解决方案

你的代码问题核心是userId当前通过@Query注解传递,会作为URL拼接参数,而非form-data请求体中的参数,大多数上传接口要求所有参数都放在form-data结构体中,按以下调整即可:


方案1:单独声明userId为Part参数

调整接口定义

@Multipart
@POST("upload/profile")
// 注意需要给Call指定对应返回结果的实体类泛型
fun uploadProfilePhoto(
    @Part image: MultipartBody.Part,
    @Part("userId") userId: RequestBody
): Call<你的返回结果实体类>

调整参数构建代码

// 构建图片请求体
val photoContent = RequestBody.create(MediaType.parse("image/*"), file)
val photo = MultipartBody.Part.createFormData("image", file.name, photoContent)
// 构建userId请求体
val userIdRequestBody = RequestBody.create(MediaType.parse("text/plain"), "实际要传的userId字符串")
// 发起请求时传入两个参数即可
api.uploadProfilePhoto(photo, userIdRequestBody).enqueue(/* 你的回调逻辑 */)

方案2:用PartMap统一管理文本参数(适合后续要扩展多个文本参数的场景)

调整接口定义

@Multipart
@POST("upload/profile")
fun uploadProfilePhoto(
    @Part image: MultipartBody.Part,
    @PartMap formParams: Map<String, RequestBody>
): Call<你的返回结果实体类>

调整参数构建代码

// 构建图片请求体
val photoContent = RequestBody.create(MediaType.parse("image/*"), file)
val photo = MultipartBody.Part.createFormData("image", file.name, photoContent)
// 构建form参数集合
val formParams = mutableMapOf<String, RequestBody>()
formParams["userId"] = RequestBody.create(MediaType.parse("text/plain"), "实际要传的userId字符串")
// 发起请求
api.uploadProfilePhoto(photo, formParams).enqueue(/* 你的回调逻辑 */)

额外排查点

  • 如果后端明确要求userId放在URL参数中,那原接口定义无需调整,可添加OkHttp日志拦截器查看实际请求的参数和路径是否符合预期
  • 确认后端约定的图片字段名是否为image、userId字段名是否完全匹配,字段名不匹配会导致后端无法取值
  • 若在Android 10及以上版本运行,确保已经拿到文件读取权限,不要直接将Content Uri转为File使用,需要通过ContentResolver正确读取文件数据
  • 必须给Call指定泛型类型,否则Retrofit序列化响应结果时会抛出异常

内容的提问来源于stack exchange,提问作者Muhammad Babar Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:45:10