I have following example which works well using curl:
curl -X 'POST' \
'https://example.com/rest/someservice?oauth_token=<token>' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@docs_recognize_ok.jpg;type=image/jpeg' \
-F 'meta={
"images": [
{
"name": "file"
}
]
}'
Can't figure out how to handle it using ktor client in Java/Kotlin?
For the moment I'm trying to handle it as:
val json = "{\n" +
" \"images\": [\n" +
" {\n" +
" \"name\": \"file\"\n" +
" }\n" +
" ]\n" +
"}"
val filesList = mutableListOf<PartData>()
val partData = formData {
append(key = "meta", value = json, headers = Headers.build {
append(HttpHeaders.ContentType, "application/json; charset=utf-8")
})
request.images.forEach { file ->
append(
"file",
InputProvider { File(file.imageFileName).inputStream().asInput() },
Headers.build {
append(HttpHeaders.ContentType, "image/jpeg")
}
)
}
}
filesList.addAll(partData)
httpClient.post("rest/someservice") {
setBody(MultiPartFormDataContent(parts = filesList))
parameters {
append("oauth_token", apiKey)
}
}
Any ideas?
The information about sending multipart/form-data requests with the Ktor client can be found in the documentation. Here is a more or less direct translation of your curl command:
val client = HttpClient(CIO)
client.post("https://example.com/rest/someservice?oauth_token=<token>") {
header(HttpHeaders.Accept, "application/json")
setBody(
MultiPartFormDataContent(
formData {
append(
"meta", """{
"images": [
{
"name": "file"
}
]
}""".trimIndent()
)
append("file", File("docs_recognize_ok.jpg").readBytes(), Headers.build {
append(HttpHeaders.ContentType, "image/jpeg")
append(HttpHeaders.ContentDisposition, "filename=\"docs_recognize_ok.jpg\"")
})
},
)
)
}
Also, here is a code generated by my tool c2k for Ktor 3.*:
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://example.com/rest/someservice?oauth_token=<token>") {
headers.append("accept", "application/json")
headers.append("Content-Type", "multipart/form-data")
setBody(MultiPartFormDataContent(formData {
val docs_recognize_ok = File("docs_recognize_ok.jpg")
append("file", ChannelProvider(size = docs_recognize_ok.length()) { docs_recognize_ok.readChannel() }, Headers.build {
append(HttpHeaders.ContentType, "image/jpeg")
append(HttpHeaders.ContentDisposition, "filename=\"${docs_recognize_ok.name}\"")
})
append("meta", """{
"images": [
{
"name": "file"
}
]
}""".trimIndent())
}))
}
print(response.bodyAsText())
}