*Update (02/28/2025): Resolved by removing ByteRea...
# ktor
c
Update (02/28/2025): Resolved by removing ByteReadChannel in
setBody()
call as suggested by @Aleksei Tirman [JB].
Final line:
setBody(Res.readBytes(path))
Hi all, wondering if I could get some guidance. I have a KMP project where I have to POST a binary file that is 1.5MB.
Copy code
fun httpPostBinary(url: String, path: String): String {
        val client = HttpClient()
        val scope = CoroutineScope(Dispatchers.IO)
        var res = 0
        scope.launch {
            try {
                PrintLnLogger.info("Sending request to: $url")

                val response: HttpResponse = client.post(url) {
                    header(HttpHeaders.Accept, "text/html")
                    header(HttpHeaders.Connection, "keep-alive")
                    header(HttpHeaders.ContentType, "application/octet-stream")
                    setBody(ByteReadChannel(Res.readBytes(path)))
                    onUpload { bytesSentTotal, contentLength ->  PrintLnLogger.info("Sent $bytesSentTotal bytes from $contentLength")}
                }

                PrintLnLogger.info("Response: ${response.status.value}")
                PrintLnLogger.info("Response: ${response.bodyAsText()}")
                res = response.status.value

            } catch (e: Exception) {
                PrintLnLogger.info("POST call failed: $e")
            }
        }

        return res.toString()
    }
Running in iOS with Darwin engine returns no issues. When I run it on Android using OkHttp or CIO, I get a SocketException error during transmitting and am able to successfully transfer only some bytes. Any clue what I'm missing? Versions • ktor: 2.3.0/ / Compatible with rsocket version and tested other version (2.0.0 and 2.1.1) • rsocket: 0.16.0 My configs
Copy code
// OkHttp
config {
            retryOnConnectionFailure(true)
            connectTimeout(1, TimeUnit.MINUTES)
        }

// CIO
engine {
        maxConnectionsCount = 1000
        endpoint {
            maxConnectionsPerRoute = 100
            pipelineMaxSize = 20
            keepAliveTime = 60000
            connectTimeout = 60000
            connectAttempts = 5
            socketTimeout = 0
        }
}
Stack trace:
Copy code
: POST call failed: java.net.SocketException: Connection reset
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:121)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at java.net.SocketOutputStream.write(SocketOutputStream.java:161)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.OutputStreamSink.write(JvmOkio.kt:56)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.AsyncTimeout$sink$1.write(AsyncTimeout.kt:127)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:256)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.RealBufferedSink.write(RealBufferedSink.kt:147)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSink.write(Http1ExchangeCodec.kt:303)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.ForwardingSink.write(ForwardingSink.kt:29)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.connection.Exchange$RequestBodySink.write(Exchange.kt:218)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:256)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okio.RealBufferedSink.writeAll(RealBufferedSink.kt:195)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at io.ktor.client.engine.okhttp.StreamRequestBody.writeTo(StreamRequestBody.kt:24)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:59)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2025-02-27 16:32:35.418  11099-12778 System.out              com.proj.package         I  	at java.lang.Thread.run(Thread.java:923)
b
are you able to post the stack trace?
c
@Bruno Medeiros I've updated it with the stack trace
h
Why did you set the socketTimeout to 0?
I would rewrite that post call so that instead of reading the entire file and then posting it, you do it in chunks. Your current method will be slow and use lots of memory
a
Can you try to pass the
Res.readBytes(path)
to the
setBody
call directly instead of wrapping it in the
ByteReadChannel
?
c
@hellman sorry that was a typo I was playing around with the different settings the socketTimeout was set to 180000 and I moved it to this section
Copy code
install(HttpTimeout) {
        socketTimeoutMillis = 180000
        connectTimeoutMillis = 180000
    }
@Aleksei Tirman [JB] 🤡 for me as that totally fixed it. Thanks for all your help!
Follow up question. It looks like this works sometimes but not consistently. I am getting Socket timeout Error:
Copy code
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  i: POST call failed: java.net.SocketTimeoutException: Socket timeout has expired [url=<http://192.168.4.1:3331/firmware_upgrade>, socket_timeout=unknown] ms
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at io.ktor.client.network.sockets.TimeoutExceptionsKt.SocketTimeoutException(TimeoutExceptions.kt:30)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at io.ktor.client.plugins.HttpTimeoutKt.SocketTimeoutException(HttpTimeout.kt:272)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at io.ktor.client.engine.okhttp.OkUtilsKt.mapOkHttpException(OkUtils.kt:82)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at io.ktor.client.engine.okhttp.OkUtilsKt.access$mapOkHttpException(OkUtils.kt:1)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at io.ktor.client.engine.okhttp.OkHttpCallback.onFailure(OkUtils.kt:42)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:525)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at java.lang.Thread.run(Thread.java:923)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  Caused by: java.net.SocketTimeoutException: timeout
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at okio.SocketAsyncTimeout.newTimeoutException(JvmOkio.kt:146)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at okio.AsyncTimeout.access$newTimeoutException(AsyncTimeout.kt:186)
2025-02-28 13:48:20.966  12937-14569 System.out              com.proj.package         I  	at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:390)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okio.RealBufferedSource.indexOf(RealBufferedSource.kt:455)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:348)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http1.HeadersReader.readLine(HeadersReader.kt:29)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:180)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:110)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:93)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	... 3 more
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  Caused by: java.net.SocketException: Socket closed
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at java.net.SocketInputStream.read(SocketInputStream.java:209)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at java.net.SocketInputStream.read(SocketInputStream.java:144)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okio.InputStreamSource.read(JvmOkio.kt:93)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:153)
2025-02-28 13:48:20.967  12937-14569 System.out              com.proj.package         I  	... 20 more