I'm trying to download a file from the internet using Ktor.
I've tried using the following code:
val response = client.get(downloadLink) {
onDownload { bytesSentTotal, contentLength ->
println("Downloaded $bytesSentTotal of $contentLength")
}
}.bodyAsChannel()
The complete code is here. This is running on a Pixel 7 with Android 14 beta 1.1.
In this example, downloadLink is this. The file is an empty text file (named test.txt). I've also tried downloading a text file with contents, but the same error occurs. What am I doing wrong?
FATAL EXCEPTION: main
Process: nl.tiebe.otarium, PID: 13700
io.ktor.client.call.NoTransformationFoundException: No transformation
found: class io.ktor.utils.io.ByteBufferChannel (Kotlin reflection is
not available) -> class kotlinx.serialization.json.JsonObject (Kotlin
reflection is not available)
with response from https://files.magister.net/file?md5=qEbVw5h-Pn0GvwaZrDpafw&expires=1682650029&m=dGV4dC9wbGFpbg&f=dGVzdC50eHQ&p=ZmlsZWJsb2IvbnVvdm8vM2Q2NjkxMjMtMTZiNS00MTYxLThiNjgtODYzZTFmNDk2OGM2L2ZpbGU&d=YXR0YWNobWVudA:
status: 200
response headers:
accept-ranges: bytes
, content-disposition: attachment; filename=test.txt
, content-length: 0
, content-type: application/octet-stream
, date: Fri, 28 Apr 2023 01:47:09 GMT
, etag: "d20e008ed58d72511427b6538372a7c4"
, last-modified: Wed, 26 Apr 2023 11:07:53 GMT
, server: nginx
, strict-transport-security: max-age=31536000
at io.ktor.client.call.HttpClientCall.bodyNullable(HttpClientCall.kt:93)
at io.ktor.client.call.HttpClientCall.body(HttpClientCall.kt:114)
at dev.tiebe.magisterapi.api.messages.MessageFlow.getDownloadLink(MessageFlow.kt:179)
at dev.tiebe.magisterapi.api.messages.MessageFlow$getDownloadLink$1.invokeSuspend(Unknown Source:15)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:68)
at kotlinx.coroutines.internal.DispatchedContinuation.resumeWith(DispatchedContinuation.kt:345)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:135)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:109)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:11)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:59)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8180)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:946)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@4910176, Dispatchers.Main.immediate]
Turns out my function for retrieving the correct download link was incorrect. I used the following code for downloading the file in the end:
val response = client.get(attachment.links.downloadLink.href) { // make sure this is the correct link!
onDownload { bytesSentTotal, contentLength ->
println("Downloaded $bytesSentTotal of $contentLength")
}
}.bodyAsChannel()