Will some kind of `ApplicationCall.receiveFile/s()...
# ktor
d
Will some kind of
ApplicationCall.receiveFile/s()
be added to Ktor? Or is it too application specific?
m
You can
receiveMultipart()
e
d
Right, it could be a nice convenience method for most cases...
m
Perhaps, though I'm not sure what it would do that receiveMultipart doesn't? It gives you access to each file's bytes, plus associated metadata (filename, content type, etc)
d
Just an easy way to receive a file for most common cases without all the boilerplate code...
m
call.receiveMultipart().readAllParts().map { it.streamProvider().use { it.readAllBytes() } }
🤷‍♂️
d
Copy code
suspend fun ApplicationCall.receiveFile(uploadDir: String): File =
		receiveMultipart().readPart().let {
			if (it is PartData.FileItem) {
				val ext = File(it.originalFileName).extension
				val uploadName = "upload-${System.currentTimeMillis()}-${it.originalFileName!!.hashCode()}.$ext"

				File(uploadDir, uploadName).also { file ->
					withContext(CommonPool) {
						it.streamProvider().use { its -> file.outputStream().buffered().use { its.copyToSuspend(it) } }
					}
				}
			} else error("Error retreiving upload")
		}

suspend fun ApplicationCall.receiveFiles(uploadDir: String): Map<String, File> =
		receiveMultipart().readAllParts().map {
			if (it is PartData.FileItem) {
				it.name!! to File(uploadDir, it.originalFileName).also { file ->
					withContext(CommonPool) {
						it.streamProvider().use { its -> file.outputStream().buffered().use { its.copyToSuspend(it) } }
					}
				}
			} else error("Error retreiving upload")
		}.toMap()
m
It's possible, certainly, but you're making a lot of decisions for the consumer of that, including defaulting to letting an HTTP request dictate a filename used on the local filesystem, which is super dangerous
d
That was my original question, if 80% of such needs could be covered with a nicely thought out implementation and a few parameters... it might still be nice 😉
m
Yep... perhaps as a standalone library