Any pointers towards how to create a stream from o...
# ktor
a
Any pointers towards how to create a stream from okio (or any other multiplatform io lib?) so that i can post a file via ktor client? Can't seem to figure out the wiring
a
Can you describe the input and the output?
a
let me share some code
Currently my code looks like this:
Copy code
httpClient.submitFormWithBinaryData(POST_URL,
                                        formData = formData {
                                            val byteArray = source
                                                .use {
                                                    it.buffer()
                                                        .use { bufferFileSource ->
                                                            bufferFileSource.readByteArray()
                                                        }
                                                }

                                            append("file", byteArray, Headers.build {
                                                append(
                                                    HttpHeaders.ContentType,
                                                    ContentType.Image.Any
                                                )
                                                append(
                                                    HttpHeaders.ContentDisposition,
                                                    "filename=\"$fileName\""
                                                )
                                            }
                                            )
                                        }
                                    )
I am concerned about this because it reads the file in one go and I want to support really big files
I am trying to figure out how to go from Okio's
Source
to 'something' (not sure about the API yet) that can upload the file without reading it in one go, to avoid OOM errors
a
You can convert the
Source
to
InputStream
and then to
Input
. Here is an example:
Copy code
val source = FileSystem.SYSTEM.source("archive.zip".toPath())
val client = HttpClient(OkHttp)

val response = client.submitFormWithBinaryData("<https://httpbin.org/post>", formData = formData {
    append("file", InputProvider(null) { source.buffer().inputStream().asInput() }, Headers.build {
        append(HttpHeaders.ContentType, ContentType.Image.Any)
        append(HttpHeaders.ContentDisposition, "filename=\"file.bin\"")
    })
})

println(response.bodyAsText())
a
@Aleksei Tirman [JB] where is
.inputStream()
from? the IDE says it's in the kotlin's stdlib but I added it in the commonMain dependencies and it doesn't pick i tup
a
It's from the okio library
a
Ah I see.
InputStream
is a java API. that is not available for multiplatform
a
Ah yeah. That will work only on JVM.
a
that's a good hint. now i know what I need to convert it to. will have a look how the
.inputStream()
and
.asInput()
works under the hood and will try to do a
buffer().asInput()
tomorrow. If that piece of code already exists somewhere, it would be super helpful
I think I go it. Need to test more but seems to work with a quick test:
Copy code
private fun BufferedSource.asInput(): Input {
    val source = this
    return object : Input() {
        override fun fill(destination: Memory, offset: Int, length: Int): Int {
            val buffer = ByteArrayPool.borrow()
            try {
                val rc = source.read(buffer, 0, minOf(buffer.size, length))
                if (rc == -1) return 0
                destination.storeByteArray(offset, buffer, 0, rc)
                return rc
            } finally {
                ByteArrayPool.recycle(buffer)
            }
        }

        override fun closeSource() {
            source.close()
        }
    }
}