Невозможно загрузить файл с помощью Ktor в Kotlin Multiplatform

Я пытаюсь загрузить файл из Интернета с помощью Ktor.

Я пробовал использовать следующий код:

val response = client.get(downloadLink) {
    onDownload { bytesSentTotal, contentLength ->
        println("Downloaded $bytesSentTotal of $contentLength")
    }
}.bodyAsChannel()

Полный код здесь. Это работает на Pixel 7 с Android 14 beta 1.1.

В этом примере ссылка для скачивания — это это. Это пустой текстовый файл (с именем test.txt). Я также пытался загрузить текстовый файл с содержимым, но возникает та же ошибка. Что я делаю не так?

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]

Отвечает ли это на ваш вопрос? ktor выдает для некоторых классов данных исключение NoTransformationFoundException

dominicoder 28.04.2023 07:11

На какой цели вы выполняете приведенный выше код? Пожалуйста, обновите свой вопрос, указав полный фрагмент кода.

Aleksei Tirman 28.04.2023 08:29

@dominicoder Этот вопрос касается ошибок в сериализации. Мой код не должен ничего сериализовать, я думаю, он выдает ошибку, потому что Ktor не знает, что делать с content-type: application/octet-stream, но я не уверен.

Tiebe Groosman 28.04.2023 13:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оказывается, моя функция для получения правильной ссылки для скачивания была неправильной. Я использовал следующий код для загрузки файла в конце:

val response = client.get(attachment.links.downloadLink.href) { // make sure this is the correct link!
    onDownload { bytesSentTotal, contentLength ->
        println("Downloaded $bytesSentTotal of $contentLength")
    }
}.bodyAsChannel()

Другие вопросы по теме