Making a Multipart API Call in Ktor with Jetpack Compose: A Simple Guide
In Android development, you might encounter scenarios where you need to send images or other files to a server. This can seem tricky, but with Ktor and Jetpack Compose, it’s simpler than you think. In this post, we’ll walk through how to make a multipart API call in Ktor to upload an image using Jetpack Compose.
Why Ktor and Jetpack Compose?
Ktor is a powerful framework for building connected applications. It makes handling HTTP requests and responses straightforward. Jetpack Compose is Android’s modern toolkit for building native UI. Combining these two allows you to create smooth, responsive, and visually appealing apps while handling complex backend interactions effortlessly.
Setting Up Ktor
First, you need to add the necessary dependencies to your build.gradle
file:
implementation("io.ktor:ktor-client-core:2.x.x")
implementation("io.ktor:ktor-client-cio:2.x.x")
implementation("io.ktor:ktor-client-content-negotiation:2.x.x")
implementation("io.ktor:ktor-client-json:2.x.x")
implementation("io.ktor:ktor-client-serialization:2.x.x")
Replace 2.x.x
with the latest version available.
Creating the Multipart Request
Let’s create a simple function to send an image to a server.
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.engine.cio.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.coroutines.*
import java.io.File
suspend fun uploadImage(imageFile: File): HttpResponse {
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json()
}
}
return client.use {
it.submitFormWithBinaryData(
url = "https://yourapi.com/upload",
formData = formData {
append(
"image",
imageFile.readBytes(),
Headers.build {
append(HttpHeaders.ContentType, ContentType.Image.Any)
append(HttpHeaders.ContentDisposition, "filename=${imageFile.name}")
}
)
}
)
}
}
Explanation:
HttpClient(CIO)
: Creates a new HTTP client with the CIO engine.install(ContentNegotiation)
: Configures the client to use JSON for content negotiation.submitFormWithBinaryData
: Sends a form with binary data (in this case, an image).formData
: Constructs the form data with the image file.
Integrating with Jetpack Compose
Now, let’s integrate this function with a simple UI built using Jetpack Compose. We’ll create a button that, when clicked, will trigger the image upload.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import java.io.File
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
UploadImageScreen()
}
}
}
@Composable
fun UploadImageScreen() {
var isUploading by remember { mutableStateOf(false) }
val context = LocalContext.current
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize().padding(16.dp)
) {
Button(
onClick = {
isUploading = true
// Replace with your actual image file path
val imageFile = File(context.cacheDir, "example.png")
CoroutineScope(Dispatchers.IO).launch {
val response = uploadImage(imageFile)
isUploading = false
// Handle the response (e.g., show a success message)
}
},
enabled = !isUploading
) {
Text(if (isUploading) "Uploading..." else "Upload Image")
}
}
}
Conclusion
That’s it! With these simple steps, you can now upload images from your Android app using Ktor and Jetpack Compose. This combination provides a robust and user-friendly way to handle complex tasks, all while keeping your code clean and easy to understand.
If you enjoyed this tutorial, feel free to share it and stay tuned for more Android development tips and tricks!
Subscribe to my newsletter
Read articles from Mukesh Rajput directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mukesh Rajput
Mukesh Rajput
Specializing in creating scalable and maintainable applications using MVVM and Clean Architecture principles. With expertise in Ktor, Retrofit, RxJava, View Binding, Data Binding, Hilt, Koin, Coroutines, Room, Realm, and Firebase, I am committed to delivering high-quality mobile solutions that provide seamless user experiences. I thrive on new challenges and am constantly seeking opportunities to innovate in the Android development space.