https://kotlinlang.org logo
#ktor
Title
# ktor
d

Dominick

05/04/2021, 2:52 PM
Say a user tries hitting the endpoint with a 5 gb file, and I use this code:
Copy code
val buffer = (part as PartData.FileItem).streamProvider().buffered()
Those 5gb will never load into memory correct? Is there a way I can get the size of the uploaded file without loading it all into memory as well?
f

Fi5t

05/09/2021, 9:03 AM
You can try to use minio instead uploading a big file directly into web server. Or use this approach:
Copy code
fileItem.streamProvider().use { input ->
    path.outputStream().buffered().use { output ->
        input.copyToSuspend(output)
    }
}
...
private suspend fun InputStream.copyToSuspend(
        out: OutputStream,
        bufferSize: Int = DEFAULT_BUFFER_SIZE,
        yieldSize: Int = 4 * 1024 * 1024,
        dispatcher: CoroutineDispatcher = <http://Dispatchers.IO|Dispatchers.IO>
    ): Long {
        return withContext(dispatcher) {
            val buffer = ByteArray(bufferSize)
            var bytesCopied = 0L
            var bytesAfterYield = 0L
            while (true) {
                val bytes = read(buffer).takeIf { it >= 0 } ?: break
                out.write(buffer, 0, bytes)
                if (bytesAfterYield >= yieldSize) {
                    yield()
                    bytesAfterYield %= yieldSize
                }
                bytesCopied += bytes

                if (bytesCopied > MAX_UPLOADING_FILE_SIZE) {
                    throw TooBigFileException("The file is too big.")
                }

                bytesAfterYield += bytes
            }
            return@withContext bytesCopied
        }
    }