It's mostly an internal detail for the channel pri...
# ktor
a
It's mostly an internal detail for the channel primitives.
u
Then im confused by the blog post https://blog.jetbrains.com/kotlin/2024/10/ktor-3-0/#breaking-changes should I or not use
bodyAsChannel
to download a file?
a
Yes, you can use the
ByteReadChannel
to save a response body to a file:
Copy code
client.get("<https://example.com>").bodyAsChannel()
    .copyTo(File("/path/to/file").writeChannel())
u
gotcha btw dont I need to
.use { .. }
?
a
For what receiver?
u
the channel or file
im coming from retrofit & inputstream so I've no idea what im doing really
a
No, but it's better to call
copyAndClose
instead of
copyTo
to close the
ByteWriteChannel
associated with the file.
u
what if it throws midway?
btw what about
Source
? I read that is sort of the
InputStream
of the kotlinx.io? Isn't the channel an unnecessary abstraction?
a
what if it throws midway?
Then the channel will be closed.
The
ByteReadChannel
unlike the
Source
provides suspendable read operations.
u
Will the read channel be closed? I only see the write channel being closed in the finally block
Copy code
@OptIn(InternalAPI::class)
public suspend fun ByteReadChannel.copyAndClose(channel: ByteWriteChannel): Long {
    var result = 0L
    try {
        while (!isClosedForRead) {
            result += readBuffer.transferTo(channel.writeBuffer)
            channel.flush()
            awaitContent()
        }

        closedCause?.let { throw it }
    } catch (cause: Throwable) {
        cancel(cause)
        channel.close(cause)
        throw cause
    } finally {
        channel.flushAndClose()
    }

    return result
}
a
It's closed with the
cancel(cause)
call in the beginning of the catch block.
👍 1