Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ktor client post multipart/form-data

How can I post file as multipart/form-data use ktor client? I want to use it for telegram bot API "send document". I need to achieve the same result as the curl command

curl -F document=@"path/to/some.file" https://api.telegram.org/bot<token>/sendDocument?chat_id=<chat_id>
like image 430
abobus Avatar asked Apr 27 '26 02:04

abobus


1 Answers

You can use the submitFormWithBinaryData method to send mutlipart/form-data request. Here is a solution:

val client = HttpClient(Apache) {}

val file = File("path/to/some.file")
val chatId = "123"

client.submitFormWithBinaryData(
    url = "https://api.telegram.org/bot<token>/sendDocument?chat_id=$chatId",
    formData = formData {
        append("document", file.readBytes(), Headers.build {
            append(HttpHeaders.ContentDisposition, "filename=${file.name}")
        })
    }
)

Here is a code (generated with my tool c2k), where the entire contents of the file isn't read into memory:

import io.ktor.client.HttpClient
import io.ktor.client.request.forms.ChannelProvider
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.client.statement.bodyAsText
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.util.cio.readChannel
import java.io.File
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val client = HttpClient {
        followRedirects = false
    }
    val response = client.post("https://api.telegram.org/bot<token>/sendDocument?chat_id=<chat_id>") {
        setBody(MultiPartFormDataContent(formData {
            val some = File("path/to/some.file")
            append("document", ChannelProvider(size = some.length()) { some.readChannel() }, Headers.build {
                append(HttpHeaders.ContentType, "application/octet-stream")
                append(HttpHeaders.ContentDisposition, "filename=\"${some.name}\"")
            })
        }))
    }
    print(response.bodyAsText())
}
like image 140
Aleksei Tirman Avatar answered Apr 29 '26 21:04

Aleksei Tirman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!