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

如何使用Retrofit在API请求中同时上传图片和其他Body参数并解决报错

Retrofit 同时上传图片和文本参数报错解决方案

核心问题原因

你的代码存在3个核心错误直接导致运行报错:

  • @Multipart和@FormUrlEncoded两个注解不能同时作用于同一个请求方法,二者属于互斥的请求编码格式,文件上传场景仅保留@Multipart注解即可
  • Multipart请求中的文本参数不能直接传递String类型,需要封装为RequestBody类型
  • 上传文件的Part写法不规范,手动拼接Header的方式容易出错,应使用MultipartBody.Part统一构造

修正步骤

1. 修正API接口定义

@Multipart
@POST("/index.php/Profile/editProfile")
fun updateProfilePic(
    @HeaderMap headers: Map<String, String>,
    @Part("user_id") userId: RequestBody,
    @Part userfile: MultipartBody.Part
) : Call<UserProfilePicResponceModal>

2. 修正上传参数构造逻辑

private fun uploadProfileToDashboard(path: String) {
    var aes = Utils.getPref(
        requireContext(),
        Constants.ENCRYPTION_AES,
        "x"
    )!!
    var iv = Utils.getPref(
        requireContext(),
        Constants.ENCRYPTION_IV,
        "x"
    )!!

    val file: File = File(path)
    // 构造图片上传Part
    val requestFile = RequestBody.create("image/*".toMediaTypeOrNull(), file)
    val userFilePart = MultipartBody.Part.createFormData("file", file.name, requestFile)
    // 构造加密后的user_id参数
    val encryptUserId = AESEncryption(aes, iv).encrypt(profile.dashboardUserName)!!
    val userIdBody = RequestBody.create("text/plain".toMediaTypeOrNull(), encryptUserId)

    profileViewModel.updateProfilePicInDashboard(
        mapOf(
            "object_id" to Utils.getPref(
                requireContext(),
                Constants.ENCRYPTION_OBJ_ID,
                "x"
            )!!,
            "db_name" to Utils.getPref(
                requireContext(),
                Constants.PROVIDER_NAME,
                "x"
            )!!
        ),
        userIdBody,
        userFilePart
    )
}

3. 修正ViewModel层方法参数

fun updateProfilePicInDashboard(
    headerParams: Map<String, String>,
    user_id: RequestBody,
    image: MultipartBody.Part
) {
    val call = RetrofitClient.updateProfilePicInDashboard.updateProfilePic(headerParams , user_id , image)
    call.enqueue(object : Callback<UserProfilePicResponceModal> {
        override fun onResponse(
            call: Call<UserProfilePicResponceModal>,
            response: Response<UserProfilePicResponceModal>
        ) {
            if (response.isSuccessful) {
                Log.i("here22" , response.body().toString())
            } else {
                Log.i("here22", "请求失败,错误码:${response.code()}")
            }
        }

        override fun onFailure(call: Call<UserProfilePicResponceModal>, t: Throwable) {
            Log.i("here22" , t.message.toString())
        }
    })
}

额外注意事项

  • 检查权限配置:Android 13及以上版本需要申请READ_MEDIA_IMAGES权限,更低版本需要申请READ_EXTERNAL_STORAGE权限,权限缺失会导致读取文件时崩溃触发该报错
  • 确认传入的文件路径path有效,如果是从相册返回的Content Uri,需要先通过ContentResolver将文件拷贝到应用私有目录再生成File对象,不要直接把Uri转为File路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:06:03