Hello, everyone I am using the ktor 1.6.3 client a...
# ktor
e
Hello, everyone I am using the ktor 1.6.3 client and serialization to send requests Before that, everything worked correctly, but now I need to send an image to the chat of the application that I am doing For client settings,
defaultRequest
uses
header(HttpHeaders.ContentType, ContentType.Application.Json)
When sending via
submitFormWithBinaryData
, it returns the error
kotlinx. serialization. SerializationException: Serializer for class 'MultipartFormDataContent' is not found
I tried to change
header
for the request to send an image with
contentType
, but I get another error
io.ktor. http.UnsafeHeaderException: Header(s) [Content-Type] are controlled by the engine and cannot be set explicitly
Judging by https://youtrack.jetbrains.com/issue/KTOR-620, I can't do this Setting
contentType
for
MultipartFormDataContent
does not give anything How can I send a request with a serializable class of type
AddImageToMessage (val messageId: Int)
and attach an image to this request?
e
need more code to diagnose, but in general, content type is supposed to be set by
body
submitFormWithBinaryData
looks like it sets the
body
for you, would need to see what your block is doing
e
if I use the code from the official website. he doesn't work for me because
defaultRequest
is set in
header(HttpHeaders.ContentType, ContentType.Application.Json)
I get an error
kotlinx. serialization. SerializationException: Serializer for class 'MultipartFormDataContent' is not found
client settings
Copy code
fun getClient(): HttpClient {

        return HttpClient(CIO) {

            install(JsonFeature) {

                serializer = KotlinxSerializer(

                    Json {
                        prettyPrint = true
                        isLenient = true
                        ignoreUnknownKeys = true
                        coerceInputValues = true
                    }
                )
            }

            expectSuccess = false

            defaultRequest {

                host = BuildConfig.REST_API_ADDRESS
                url.protocol = URLProtocol.HTTPS

                header(HttpHeaders.ContentType, ContentType.Application.Json)
            }
        }
    }
request
Copy code
suspend fun addImageToMessage(
        messageId: Int,
        path: String,
        image: File
    ) {

        client.submitFormWithBinaryData<Unit>(
            formData = formData {
                append(
                    "image", image.readBytes(), Headers.build {
                        append(HttpHeaders.ContentType, "image/png")
                        append(HttpHeaders.ContentDisposition, "filename=image.png")
                    }
                )
//                append("messageId", messageId)
            }
        ) {
            url.encodedPath = path
//            body = AddImageToMessage(messageId = messageId)
        }
    }
I would also like to add
AddImageToMessage
to this request
append("messageId", messageId)
does not work in my case
a
The only thing I can suggest is to not put the
application/json
content-type in the
defaultRequest
because this header triggers content converter execution (
UnsafeHeaderException
is not thrown because because
ContentNegotiation
removes this header before the check).
So
SerializationException
is expectable and to avoid it you should not put the
application/json
content-type in the first place.
e
I tried this option, but I couldn't add the
messageId
parameter to the request body as if I sent them through the serializable
AddImageToMessage
class most likely, this should be added to the
formData
, but I do not know how
a
You can serialize it manually and append a string but I agree this is not convenient.
e
please tell me, what value I need to put for the 
key
 parameter?
Copy code
suspend fun addImageToMessage(
        messageId: Int,
        path: String,
        image: File
    ) {

        client.submitFormWithBinaryData<Unit>(
            formData = formData {
                append(
                    "image", image.readBytes(), Headers.build {
                        append(HttpHeaders.ContentType, "image/png")
                        append(HttpHeaders.ContentDisposition, "filename=image.png")
                    }
                )

                val messageIdJson = JSONObject().apply {
                    put("messageId", messageId)
                }

                append(key = "?",value = messageIdJson.toString())
            }
        ) {
            url.encodedPath = path
        }
    }
a
@Evgeny Berezovsky, what HTTP request do you want to construct? The key is the name of a part.
e
for example, if I send just a 
messageId
 with 
ContentType=application/json
 without an attached image, then in the logs it will look like this but when I attach an image and change 
ContentType=multipart/form-data
, I do not know how to add information about the 
messageId
 so that the server sees it
an endpoint that I used for request, most likely does not work correctly I tried another endpoint and it worked
append(key = "messageId",value = messageId)
in
formData
works for me thank you very much)
👍 1