Now I had a problem to send a picture with some additional data to Web Api .NET Core.

Server side is same as I already explained here

Api service:

interface IWebApiService {
    @Headers("Content-Type: text/json")
    @POST("UploadImage")
    fun uploadImage(@Body image: JsonObject): Call<UploadResponse>
}

data class UploadResponse(
    @SerializedName("message")
    val message: String
)
Upload image:
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import androidx.annotation.RequiresApi
import com.google.gson.JsonObject
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.ByteArrayOutputStream
import java.util.Base64

class UploadImageRetrofit(private val uploadImageRetrofitCallBacks: IUploadImageRetrofitCallBacks, private val webApiService: IWebApiService) {
    @RequiresApi(Build.VERSION_CODES.O)
    fun uploadImage(imgUri: Uri, context: Context): String? {

        val base64Image = convertImageToBase64(context, imgUri)
        val jsonValue = JsonObject().apply {
            addProperty("image", base64Image)
            addProperty("fileName", "magnolia.jpg")
            addProperty("folderName", "spring")
        }
        val webApiRequest = webApiService.uploadImage(jsonValue)

        webApiRequest.enqueue(object : Callback<UploadResponse> {
            override fun onResponse(call: Call<UploadResponse>, response: Response<UploadResponse>) {
                uploadImageRetrofitCallBacks.onResponse(call, response)
            }

            override fun onFailure(call: Call<UploadResponse>, t: Throwable) {
                uploadImageRetrofitCallBacks.onFailure(call, t)
            }
        })

        return null
    }

    @RequiresApi(Build.VERSION_CODES.O)
    fun convertImageToBase64(context: Context, imgUri: Uri): String {
        val inputStream = context.contentResolver.openInputStream(imgUri)
        val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
        val baos = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
        val imageBytes: ByteArray = baos.toByteArray()
        return Base64.getEncoder().encodeToString(imageBytes)
    }
}

Rest is same as in previous example.

Download from here.

---

UPDATE 2024-04-06: The convertImageToBase64 method in the above example will delete EXIF data, in order not to loose EXIF data use something like this:

@RequiresApi(Build.VERSION_CODES.O)
fun convertImageToBase64(context: Context, imgUri: Uri): String {
	val inputStream = context.contentResolver.openInputStream(imgUri)
	val imageBytes = inputStream.use { input ->
		input?.readBytes()
	} ?: return "" // Handle null input stream or read failure

	return Base64.getEncoder().encodeToString(imageBytes)
}