使用Jetpack Compose+Retrofit传头像遇400错误:缺少[image]参数求助
Retrofit上传头像400错误及API28以下未上传问题排查
一、400错误:Required Part [image] not specified
问题原因
服务器要求的表单字段名是image,但你在创建MultipartBody.Part时使用了"avatar",字段名不匹配导致服务器无法识别上传的文件。
修复方案
将createFormData的第一个参数从"avatar"改为"image",修改后的ViewModel代码如下:
fun uploadMyPhotoRequest(image: Bitmap) { val stream = ByteArrayOutputStream() image.compress(Bitmap.CompressFormat.JPEG, 80, stream) val byteArray = stream.toByteArray() val body = MultipartBody.Part.createFormData( "image", "photo", // 替换字段名为服务器要求的"image" byteArray.toRequestBody("image/jpeg".toMediaTypeOrNull(), 0, byteArray.size) ) viewModelScope.launch { try { apiService.uploadPhoto(body) } catch (e: Exception) { e.message } } }
二、API28以下版本未触发上传
问题原因
Composable代码中,API28以下分支仅更新了profileImageBitmap变量,未调用uploadMyPhotoRequest上传方法,导致上传逻辑未执行。
修复方案
在API28以下分支中,设置完profileImageBitmap后调用上传方法,修改后的Composable代码如下:
val photoPicker = rememberLauncherForActivityResult( contract = ActivityResultContracts.PickVisualMedia(), ) { uri -> if (uri != null) { if (Build.VERSION.SDK_INT < 28) { profileImageBitmap.value = MediaStore.Images.Media.getBitmap(ctx.contentResolver, uri) // 新增上传调用,使用?.let避免空指针 profileImageBitmap.value?.let { mainViewModel.uploadMyPhotoRequest(it) } } else { val source = ImageDecoder.createSource(ctx.contentResolver, uri) profileImageBitmap.value = ImageDecoder.decodeBitmap(source) mainViewModel.uploadMyPhotoRequest(profileImageBitmap.value!!) } } }
额外提示:API28以下的MediaStore.Images.Media.getBitmap已被废弃,建议统一使用ImageDecoder或第三方图片加载库(如Glide)处理图片加载,避免废弃方法的潜在问题。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

