Клиент Ktor OutOfMemoryError при загрузке больших файлов

val client = HttpClient(CIO) {
    install(HttpTimeout) {
      val timeout = 30_000L
      requestTimeoutMillis = timeout
      connectTimeoutMillis = timeout
    }
}

val response =
    client.get("https://example.com/large.PDF") {
       header("Authorization", "Bearer $token")
          timeout {
             connectTimeoutMillis = 1024 * 1024 * 20
             requestTimeoutMillis = 1024 * 1024 * 20
             socketTimeoutMillis = 1024 * 1024 * 20
          }
     }.bodyAsChannel()
 }

и я получил эту ошибку

e.myapplication: Background concurrent copying GC freed 115239(5068KB) AllocSpace objects, 680(13MB) LOS objects, 15% free, 133MB/157MB, paused 101us,14us total 256.669ms
e.myapplication: Waiting for a blocking GC Alloc
e.myapplication: WaitForGcToComplete blocked Alloc on Background for 13.355ms
e.myapplication: Starting a blocking GC Alloc
e.myapplication: Forcing collection of SoftReferences for 129MB allocation
e.myapplication: Starting a blocking GC Alloc
e.myapplication: Alloc concurrent copying GC freed 717(26KB) AllocSpace objects, 0(0B) LOS objects, 14% free, 136MB/160MB, paused 533us,11us total 77.959ms
e.myapplication: Throwing OutOfMemoryError "Failed to allocate a 135362867 byte allocation with 25165824 free bytes and 55MB until OOM, target footprint 168736728, growth limit 201326592" (VmSize 14920168 kB)
e.myapplication: Starting a blocking GC Alloc
e.myapplication: Starting a blocking GC Alloc
e.myapplication: Forcing collection of SoftReferences for 129MB allocation
e.myapplication: Starting a blocking GC Alloc
e.myapplication: Alloc concurrent copying GC freed 10(272B) AllocSpace objects, 0(0B) LOS objects, 14% free, 136MB/160MB, paused 136us,20us total 42.253ms
e.myapplication: Throwing OutOfMemoryError "Failed to allocate a 135362872 byte allocation with 25165824 free bytes and 55MB until OOM, target footprint 168736528, growth limit 201326592" (VmSize 14920168 kB)

java.lang.OutOfMemoryError: Failed to allocate a 135362872 byte allocation with 25165824 free bytes and 49MB until OOM, target footprint 174097912, growth limit 201326592
        at io.ktor.utils.io.core.StringsKt.readBytes(Strings.kt:168)
        at io.ktor.utils.io.core.StringsKt.readBytes$default(Strings.kt:165)
        at io.ktor.client.call.SavedCallKt.save(SavedCall.kt:73)
        at io.ktor.client.call.SavedCallKt$save$1.invokeSuspend(Unknown Source:13)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at android.os.Handler.handleCallback(Handler.java:942)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@1bf4999, Dispatchers.Main.immediate]

размер файла составляет около ~ 150 МБ

KtorVersion = 2.1.3

Плохая идея помещать такой большой файл в переменную типа var response. Лучше найдите способ напрямую сохранить байты в файл.

blackapps 01.12.2022 14:37
0
1
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я нашел правильный путь. Спасибо за направление.

client.prepareGet("https://example.com/large.PDF").execute { httpResponse ->
        val channel: ByteReadChannel = httpResponse.body()
        while (!channel.isClosedForRead) {
            val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
            while (!packet.isEmpty) {
                val bytes = packet.readBytes()
                file.appendBytes(bytes)
            }
        }
        println("A file saved to ${file.path}")
    }

Приятно видеть небольшой намек, ведущий к успеху ;-) (И в течение получаса!).

blackapps 01.12.2022 15:32

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