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

如何用Retrofit2发送带图片的Multipart请求?413错误排查

问题描述

需要发送与Postman中相同的Multipart请求,使用Retrofit结合Coroutines开发,但服务器返回413(实体过大)错误,Postman发送相同请求却正常。相关代码如下:

Retrofit接口定义

@POST("ia")
@Multipart
suspend fun getMeasurement(
    @HeaderMap authenticationHeaders: ApiHeaders,
    @Part("userId") userId: RequestBody,
    @Part("sessionId") sessionId: RequestBody,
    @Part file: MultipartBody.Part,
    @Part file2: MultipartBody.Part,
    @Part file3: MultipartBody.Part,
    @Part file4: MultipartBody.Part,
): Response<MeasurementResponse>

创建MultipartBody.Part的代码

fun createImageRequestBody(imageUri: Uri, fileName: String): MultipartBody.Part? {
        context.contentResolver?.query(imageUri, null, null, null, null)?.use {
            if (it.moveToFirst()) {
                val picturePath =
                    it.getString(it.getColumnIndex(MediaStore.MediaColumns.DATA))

                val requestBody = File(picturePath).asRequestBody("image/jpeg".toMediaTypeOrNull())
                return MultipartBody.Part.createFormData(
                    "file",
                    "${fileName}.jpeg",
                    requestBody
                )
            }
        }
        return null
    }

创建其他参数的代码

val userId = user.id.toRequestBody("text/plain".toMediaTypeOrNull())

val sessionId = session.id.toRequestBody("text/plain".toMediaTypeOrNull())

问题排查与解决方法

1. 废弃字段导致文件读取异常

Android 10(API 29)及以上版本中,MediaStore.MediaColumns.DATA字段已被废弃,通过这个字段获取的文件路径可能无效,导致你读取的不是目标图片,甚至误读取了更大的无关文件,最终触发服务器的大小限制。

解决代码:改用ContentResolver直接读取文件流,避免依赖废弃路径:

fun createImageRequestBody(imageUri: Uri, fileName: String): MultipartBody.Part? {
    context.contentResolver.openInputStream(imageUri)?.use { inputStream ->
        val tempFile = File(context.cacheDir, "${fileName}.jpeg").apply {
            inputStream.copyTo(outputStream())
        }
        val requestBody = tempFile.asRequestBody("image/jpeg".toMediaTypeOrNull())
        return MultipartBody.Part.createFormData(
            "file",
            "${fileName}.jpeg",
            requestBody
        )
    }
    return null
}

2. 未压缩图片导致体积过大

Postman中使用的图片可能经过压缩,而你的代码直接读取原始图片文件,体积远大于Postman发送的版本,触发服务器的大小阈值。

解决代码:添加图片压缩逻辑,将图片压缩到合适大小后再构建请求体:

// 图片压缩工具方法,可根据需求调整压缩质量
fun compressImage(uri: Uri, context: Context): File? {
    val bitmap = BitmapFactory.decodeStream(context.contentResolver.openInputStream(uri))
    val outputStream = ByteArrayOutputStream()
    // 保留80%质量,可根据需要调整数值(0-100)
    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream)
    val compressedFile = File(context.cacheDir, "compressed_${System.currentTimeMillis()}.jpg")
    compressedFile.outputStream().use {
        it.write(outputStream.toByteArray())
    }
    bitmap.recycle()
    return compressedFile
}

// 修改后的createImageRequestBody
fun createImageRequestBody(imageUri: Uri, fileName: String): MultipartBody.Part? {
    val compressedFile = compressImage(imageUri, context) ?: return null
    val requestBody = compressedFile.asRequestBody("image/jpeg".toMediaTypeOrNull())
    return MultipartBody.Part.createFormData(
        "file",
        "${fileName}.jpeg",
        requestBody
    )
}

3. Multipart参数名称不匹配

检查Postman中的文件参数名:如果Postman里的文件参数是file1、file2、file3、file4,而你的代码中所有文件的参数名都是file,可能导致服务器解析异常,或误判请求数据大小。

解决方法:根据Postman的参数名调整createFormData的第一个参数:

// 对应四个文件分别设置参数名
// 第一个文件
MultipartBody.Part.createFormData("file", "${fileName1}.jpeg", requestBody1)
// 第二个文件
MultipartBody.Part.createFormData("file2", "${fileName2}.jpeg", requestBody2)
// 第三个文件
MultipartBody.Part.createFormData("file3", "${fileName3}.jpeg", requestBody3)
// 第四个文件
MultipartBody.Part.createFormData("file4", "${fileName4}.jpeg", requestBody4)

4. OkHttp请求大小限制

检查OkHttpClient的配置,是否自定义了过小的请求大小限制(默认OkHttp无严格限制,但自定义配置可能出错)。如果有如下配置,调整为足够大的值或移除:

// 错误示例:限制请求体最大10MB,若实际请求超过则触发问题
val client = OkHttpClient.Builder()
    .maxRequestBodySize(10 * 1024 * 1024)
    .build()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:51