Ktor HTTP client core library - asynchronous framework for creating HTTP clients in Kotlin multiplatform
—
Support for URL-encoded forms and multipart form data with file uploads, providing type-safe form submission capabilities.
URL-encoded form content for simple form submissions.
/**
* URL-encoded form content implementation
*/
class FormDataContent(val formData: Parameters) : OutgoingContent.ByteArrayContent() {
/** Form parameters */
val formData: Parameters
/** Content length in bytes */
override val contentLength: Long
/** Content type (application/x-www-form-urlencoded) */
override val contentType: ContentType
/**
* Get form data as byte array
*/
override fun bytes(): ByteArray
}Usage Examples:
import io.ktor.client.request.forms.*
import io.ktor.http.*
// Create form data
val formData = FormDataContent(Parameters.build {
append("username", "john_doe")
append("password", "secret123")
append("remember", "true")
})
// Send form data
val response = client.post("https://api.example.com/login") {
setBody(formData)
}Multipart form data content for complex forms with file uploads.
/**
* Multipart form data content implementation
*/
class MultiPartFormDataContent(
parts: List<PartData>,
boundary: String,
contentType: ContentType = ContentType.MultiPart.FormData.withParameter("boundary", boundary)
) : OutgoingContent.WriteChannelContent() {
/** Multipart boundary string */
val boundary: String
/** Content type (multipart/form-data) */
override val contentType: ContentType
/** Content length if determinable */
override val contentLength: Long?
/**
* Write multipart content to channel
*/
override suspend fun writeTo(channel: ByteWriteChannel)
}Convenience functions for submitting forms with various content types.
/**
* Submit URL-encoded form
*/
suspend fun HttpClient.submitForm(
formParameters: Parameters,
encodeInQuery: Boolean = false,
block: HttpRequestBuilder.() -> Unit = {}
): HttpResponse
/**
* Submit URL-encoded form with URL
*/
suspend fun HttpClient.submitForm(
url: String,
formParameters: Parameters,
encodeInQuery: Boolean = false,
block: HttpRequestBuilder.() -> Unit = {}
): HttpResponse
/**
* Submit multipart form with binary data
*/
suspend fun HttpClient.submitFormWithBinaryData(
formData: List<PartData>,
block: HttpRequestBuilder.() -> Unit = {}
): HttpResponse
/**
* Submit multipart form with binary data and URL
*/
suspend fun HttpClient.submitFormWithBinaryData(
url: String,
formData: List<PartData>,
block: HttpRequestBuilder.() -> Unit = {}
): HttpResponseUsage Examples:
// Simple form submission
val loginParams = Parameters.build {
append("username", "alice")
append("password", "secret")
}
val loginResponse = client.submitForm(
url = "https://api.example.com/login",
formParameters = loginParams
) {
headers["User-Agent"] = "MyApp/1.0"
}
// Form data in query string
val searchResponse = client.submitForm(
url = "https://api.example.com/search",
formParameters = Parameters.build {
append("q", "kotlin")
append("limit", "10")
},
encodeInQuery = true // Use GET with query parameters
)
// Multipart form with file upload
val uploadData = listOf(
PartData.FormItem("title", "My Document"),
PartData.FormItem("description", "Important document"),
PartData.FileItem(
provider = { ByteReadChannel(fileBytes) },
dispose = {},
partHeaders = headersOf(
HttpHeaders.ContentDisposition,
"form-data; name=\"file\"; filename=\"document.pdf\""
)
)
)
val uploadResponse = client.submitFormWithBinaryData(
url = "https://api.example.com/upload",
formData = uploadData
) {
headers["Authorization"] = "Bearer $token"
}Functions for creating reusable prepared form requests.
/**
* Prepare URL-encoded form submission
*/
suspend fun HttpClient.prepareForm(
formParameters: Parameters,
encodeInQuery: Boolean = false,
block: HttpRequestBuilder.() -> Unit = {}
): HttpStatement
/**
* Prepare URL-encoded form submission with URL
*/
suspend fun HttpClient.prepareForm(
url: String,
formParameters: Parameters,
encodeInQuery: Boolean = false,
block: HttpRequestBuilder.() -> Unit = {}
): HttpStatement
/**
* Prepare multipart form submission
*/
suspend fun HttpClient.prepareFormWithBinaryData(
formData: List<PartData>,
block: HttpRequestBuilder.() -> Unit = {}
): HttpStatement
/**
* Prepare multipart form submission with URL
*/
suspend fun HttpClient.prepareFormWithBinaryData(
url: String,
formData: List<PartData>,
block: HttpRequestBuilder.() -> Unit = {}
): HttpStatementUsage Examples:
// Prepare reusable form
val loginForm = client.prepareForm(
url = "https://api.example.com/login",
formParameters = Parameters.build {
append("username", "placeholder")
append("password", "placeholder")
}
)
// Use prepared form multiple times
val response1 = loginForm.execute { response ->
// Custom response handling
response.bodyAsText()
}
val response2 = loginForm.execute()Classes representing different types of form parts in multipart forms.
/**
* Base class for multipart form parts
*/
sealed class PartData {
abstract val headers: Headers
abstract val name: String?
/**
* Simple form field
*/
data class FormItem(
override val name: String,
val value: String,
override val headers: Headers = Headers.Empty
) : PartData()
/**
* Binary file part
*/
data class BinaryItem(
override val name: String?,
val contentType: ContentType?,
override val headers: Headers = Headers.Empty,
val provider: () -> ByteReadChannel
) : PartData()
/**
* File upload part
*/
data class FileItem(
override val name: String?,
val originalFileName: String?,
override val headers: Headers = Headers.Empty,
val provider: () -> ByteReadChannel,
val dispose: () -> Unit = {}
) : PartData()
/**
* Binary channel part
*/
data class BinaryChannelItem(
override val name: String?,
val contentType: ContentType?,
override val headers: Headers = Headers.Empty,
val provider: () -> ByteReadChannel
) : PartData()
}Usage Examples:
import io.ktor.http.content.*
import io.ktor.utils.io.*
import java.io.File
// Create different types of form parts
val formParts = listOf(
// Simple text field
PartData.FormItem("username", "alice"),
// File upload from File object (JVM)
PartData.FileItem(
provider = { file.readChannel() },
dispose = {},
partHeaders = headersOf(
HttpHeaders.ContentDisposition,
"form-data; name=\"avatar\"; filename=\"avatar.jpg\""
)
),
// Binary data
PartData.BinaryItem(
name = "data",
contentType = ContentType.Application.OctetStream,
provider = { ByteReadChannel(binaryData) }
),
// Binary channel
PartData.BinaryChannelItem(
name = "stream",
contentType = ContentType.Text.Plain,
provider = { dataChannel }
)
)
// Submit multipart form
val response = client.submitFormWithBinaryData(
url = "https://api.example.com/upload",
formData = formParts
)DSL for building form data with type safety.
/**
* Build form parameters using DSL
*/
fun formParameters(block: ParametersBuilder.() -> Unit): Parameters =
ParametersBuilder().apply(block).build()
/**
* Build multipart form data using DSL
*/
fun multiPartFormData(block: MultiPartFormDataContent.Builder.() -> Unit): MultiPartFormDataContentUsage Examples:
// Form parameters DSL
val params = formParameters {
append("name", "John Doe")
append("email", "john@example.com")
append("subscribe", "true")
appendAll("interests", listOf("kotlin", "web", "mobile"))
}
val response = client.submitForm(
url = "https://api.example.com/register",
formParameters = params
)
// Multipart form DSL
val multipart = multiPartFormData {
// Add text fields
append("title", "My Upload")
append("description", "File description")
// Add file
append("file", fileBytes, Headers.build {
append(HttpHeaders.ContentDisposition, "filename=document.pdf")
append(HttpHeaders.ContentType, "application/pdf")
})
}
val uploadResponse = client.post("https://api.example.com/upload") {
setBody(multipart)
}Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-client-core-iosx64