Ktor: Ktor 1.3.1 Fails File Upload with MalformedInputException

Created on 2 May 2020  路  8Comments  路  Source: ktorio/ktor

Hi. I am using Ktor Client with version 1.3.1 for MPP

I have been using Ktor version 1.2.6 in my MPP project with Kotlin version 1.3.61 and it was working fine, so I was able to upload files without a problem. Later I update Kotlin version to 1.3.72 which forced me to update Ktor version 1.3.1 as version 1.2.6 was compiled with Kotlin version 1.3.61 which IDE can not compile with Kotlin plugin 1.3.72. After that file upload call started to give me the following exception.

2020-05-02 17:35:35.186 14564-14671/com.inivo.client.debug E/AndroidRuntime: FATAL EXCEPTION: ktor-android-dispatcher-worker-2
    Process: com.inivo.client.debug, PID: 14564
    io.ktor.utils.io.charsets.MalformedInputException: Input length = 1
        at io.ktor.utils.io.charsets.CharsetJVMKt.throwExceptionWrapped(CharsetJVM.kt:323)
        at io.ktor.utils.io.charsets.CharsetJVMKt.decode(CharsetJVM.kt:199)
        at io.ktor.utils.io.charsets.EncodingKt.decode(Encoding.kt:101)
        at io.ktor.utils.io.core.StringsKt.readText(Strings.kt:251)
        at io.ktor.utils.io.core.StringsKt.readText$default(Strings.kt:250)
        at io.ktor.client.features.logging.Logging$logRequestBody$2$1.invokeSuspend(Logging.kt:111)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:184)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:108)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:307)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:317)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:249)
        at io.ktor.utils.io.ByteBufferChannel.resumeWriteOp(ByteBufferChannel.kt:2210)
        at io.ktor.utils.io.ByteBufferChannel.bytesRead(ByteBufferChannel.kt:930)
        at io.ktor.utils.io.ByteBufferChannel.readAsMuchAsPossible(ByteBufferChannel.kt:544)
        at io.ktor.utils.io.ByteBufferChannel.readAvailable$suspendImpl(ByteBufferChannel.kt:606)
        at io.ktor.utils.io.ByteBufferChannel.readAvailable(Unknown Source:0)
        at io.ktor.utils.io.jvm.javaio.WritingKt.copyTo(Writing.kt:21)
        at io.ktor.utils.io.jvm.javaio.WritingKt.copyTo$default(Writing.kt:12)
        at io.ktor.client.engine.android.AndroidClientEngineKt.writeTo(AndroidClientEngine.kt:112)
        at io.ktor.client.engine.android.AndroidClientEngine.execute(AndroidClientEngine.kt:79)
        at io.ktor.client.engine.HttpClientEngine$executeWithinCallContext$2.invokeSuspend(HttpClientEngine.kt:83)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

I am uploading a file like this.

override suspend fun sendImageAsync(
        token: String,
        file: File,
        fileType: String,
        id: Long
    ): Unit = client.request {
        fullUrl("${RestApi.SEND_IMAGE}/${id}")
        method = HttpMethod.Post
        body = MultiPartFormDataContent(
            formData {
                append(
                    "image",
                    file.fileData.bytes,
                    headers = Headers.build {
                        append(HttpHeaders.ContentType, "image/jpg")
                        append(
                            HttpHeaders.ContentDisposition,
                            "filename=${file.name}"
                        )
                        append("Connection", "Close")
                    }
                )
            }
        )
        header(HttpHeaders.Connection, "close")
        header(HttpHeaders.Authorization, makeAuthToken(token))
    }

Here file data is just an object which keeps File data as a byte array so by that I can convert image to byte array (either from Android / IOS) and upload it.

Thank you very much for your help in advanced.

bug

Most helpful comment

Hi @e5l ,
I am sorry for the late reply. I can confirm that the issue still appears with Ktor version 1.3.2.

All 8 comments

Hi @namig-accenture, thanks for the report. Could you receive the response as ByteArray and post it here?

Hi!
I have the same problem while loading pdf MultiPartFormData
Response as ByteArray is:
println("response bytes as HEX String: " + response.readBytes().toHexString()) println("response size: " + response.readBytes().size)
Output:
response bytes as HEX String:
response size: 0
Turning logging off fixes the problem but I can't use it as workaround.

Hi @e5l Sorry for the late reply,
I was uploading the file as a byte array, I was not receiving it as a byte array.
As far as I understood when Ktor logs request data (in this case images as a byte array) it crashes.
Because if I disable logging for Ktor uploading file as a byte array works fine.

Could you reproduce it with 1.3.2? We muted all logging exceptions.

Hi @e5l ,
I am sorry for the late reply. I can confirm that the issue still appears with Ktor version 1.3.2.

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

scorsi picture scorsi  路  4Comments

evgfilim1 picture evgfilim1  路  4Comments

shinriyo picture shinriyo  路  4Comments

guenhter picture guenhter  路  4Comments

seanf picture seanf  路  3Comments