#android #retrofit #multipart
#Android #переоборудование #составная часть
Вопрос:
Я пытаюсь загрузить bmp-файл на сервер (аватар). Для этого я подаю в суд на Модернизацию и Составные части. Вот часть дооснащения :
@Multipart @POST("api/media/images") suspend fun uploadImage( @Part file: MultipartBody.Part? ): UploadImageResponse
Пользователи выбирают одно изображение из галереи, а затем приложение должно загрузить его на сервер. Я использую jetpack compose в этом приложении. Вот мой компонент для выбора фотографии :
@Composable fun UploadButton(bitmapSelected: MutableStatelt;Bitmap?gt;) { var imageUri by remember { mutableStateOflt;Uri?gt;(null) } val context = LocalContext.current val launcher = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetContent() ) { uri: Uri? -gt; imageUri = uri } Column( modifier = Modifier .width(72.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top ) { IconButton( modifier = Modifier .clip(CircleShape) .size(48.dp) .background(Color.Black), onClick = { launcher.launch("image/*") }) { imageUri?.let { it -gt; if (Build.VERSION.SDK_INT lt; 28) { bitmapSelected.value = MediaStore.Images .Media.getBitmap(context.contentResolver, it) } else { val source = ImageDecoder .createSource(context.contentResolver, it) bitmapSelected.value = ImageDecoder.decodeBitmap(source) bitmapSelected.value = ImageDecoder.decodeBitmap(source) } bitmapSelected.value?.let { btm -gt; Image( bitmap = btm.asImageBitmap(), contentDescription = null, modifier = Modifier.size(40.dp), contentScale = ContentScale.Crop ) } } Spacer(modifier = Modifier.height(PaddingSmall)) } Text( textAlign = TextAlign.Center, text = stringResource(R.string.upload_profile_photo), style = MaterialTheme.typography.body2, color = Color.Black ) } }
как вы можете видеть, состояние передается в класс Screen Composable при использовании выбранного bmp:
@Composable fun CreateAccountScreen( navController: NavController, viewModel: CreateAccountViewModel = hiltViewModel() ) { ... val bitmap = remember {mutableStateOflt;Bitmap?gt;(null) } UploadButton( bitmapSelected = bitmap )
Все работает отлично. Вы можете выбрать фотографию и установить ее в качестве аватара. Однако , когда я хочу отправить фотографию как часть в бэкэнд, как это :
fun bitmapToMultipart(imageBitmap: Bitmap): MultipartBody.Part { val bos = ByteArrayOutputStream() imageBitmap.compress(Bitmap.CompressFormat.JPEG, 80 /*ignored for PNG*/, bos) val bitmapdata = bos.toByteArray() Log.i(TAG, "bitmapToMultipart: ${Base64.encodeToString(bitmapdata,Base64.NO_WRAP)}") val name: RequestBody = bitmapdata.toRequestBody("image/*".toMediaTypeOrNull(), 0, bitmapdata.size) return MultipartBody.Part.createFormData("file", "avatar", name) }
Я получаю сообщение об ошибке с сервера, что это не изображение. Что может быть не так ? В чем проблема ?
Комментарии:
1. Попробуйте использовать конкретный тип MIME, а не подстановочный знак (
image/*
).2. Не могли бы вы показать мне пример, пожалуйста ?
3. Вы кодируете свое изображение в формате JPEG (
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 80 /*ignored for PNG*/, bos)
). Тип MIME для JPEGimage/jpeg
-нетimage/*
.4.
val bitmapdata = bos.toByteArray()
? Илиval jpgdata = bos.toByteArray()
? Вы загружаете не растровое изображение, а файл jpg.
Ответ №1:
Решенный. Мне пришлось добавить .jpg в имя файла, чтобы оно было :
return MultipartBody.Part.createFormData("file", "avatar.jpg", name)