Retrofit发送Multipart图片至后端始终为空问题排查
解决方案
1. 修复文件流未关闭问题
图片流复制后未关闭,可能导致生成的文件为空,后端无法解析。修改AndroidMultipartImageProvider的getImage方法,使用use块自动管理流:
override fun getImage(uri: Uri): MultipartBody.Part { val fileDir = context.filesDir val file = File(fileDir, "image.png") // use块自动关闭流,确保文件内容写入完整 contentResolver.openInputStream(uri)?.use { inputStream -> FileOutputStream(file).use { outputStream -> inputStream.copyTo(outputStream) } } ?: throw IllegalArgumentException("无法读取图片文件") // 获取图片真实MIME类型,避免硬编码不匹配 val mimeType = contentResolver.getType(uri) ?: "image/png" val requestBody = file.asRequestBody(mimeType.toMediaTypeOrNull()) return MultipartBody.Part.createFormData( "image", file.name, requestBody ) }
2. 添加日志拦截器排查请求细节
在OkHttp中添加日志拦截器,查看实际发送的multipart表单内容,确认字段名和文件是否正确:
首先添加依赖:
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
然后修改RetrofitModule中的OkHttpClient配置:
@Provides @Singleton fun providesOkHttpClient(): OkHttpClient = OkHttpClient.Builder() .connectTimeout(TIMEOUT_MINUTES, TimeUnit.MINUTES) .readTimeout(TIMEOUT_MINUTES, TimeUnit.MINUTES) .writeTimeout(TIMEOUT_MINUTES, TimeUnit.MINUTES) .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY // 打印完整请求体 }) .build()
通过日志重点检查:
- multipart表单中是否存在
image字段 - 图片文件的大小是否正常(非0字节)
name字段是否以正确的表单键发送
3. 确认toMultipartBody()扩展函数正确性
确保字符串转MultipartPart的扩展函数指定了正确的表单字段名:
// 补充扩展函数实现 fun String.toMultipartBody(): MultipartBody.Part { val requestBody = this.toRequestBody("text/plain".toMediaTypeOrNull()) return MultipartBody.Part.createFormData("name", this) }
如果该函数未指定name作为表单键,会导致后端无法解析参数,进而影响整个multipart表单的解析。
4. 验证参数名大小写匹配
确认后端接收图片的参数名是image(与createFormData中的第一个参数完全一致),multipart表单字段名大小写敏感,需严格匹配。
内容的提问来源于stack exchange,提问作者Pierre Vieira
相关产品推荐
相关产品推荐

