Handling HTTP Uploads

Ktor supports handling HTTP Uploads. As well as receiving any other kind of content.

You can check out the Youkube example for a full example of this in action.

Receiving files using multipart

  1. val multipart = call.receiveMultipart()
  2. multipart.forEachPart { part ->
  3. when (part) {
  4. is PartData.FormItem -> {
  5. if (part.name == "title") {
  6. title = part.value
  7. }
  8. }
  9. is PartData.FileItem -> {
  10. val ext = File(part.originalFileName).extension
  11. val file = File(uploadDir, "upload-${System.currentTimeMillis()}-${session.userId.hashCode()}-${title.hashCode()}.$ext")
  12. part.streamProvider().use { input -> file.outputStream().buffered().use { output -> input.copyToSuspend(output) } }
  13. videoFile = file
  14. }
  15. }
  16. part.dispose()
  17. }
  18. suspend fun InputStream.copyToSuspend(
  19. out: OutputStream,
  20. bufferSize: Int = DEFAULT_BUFFER_SIZE,
  21. yieldSize: Int = 4 * 1024 * 1024,
  22. dispatcher: CoroutineDispatcher = Dispatchers.IO
  23. ): Long {
  24. return withContext(dispatcher) {
  25. val buffer = ByteArray(bufferSize)
  26. var bytesCopied = 0L
  27. var bytesAfterYield = 0L
  28. while (true) {
  29. val bytes = read(buffer).takeIf { it >= 0 } ?: break
  30. out.write(buffer, 0, bytes)
  31. if (bytesAfterYield >= yieldSize) {
  32. yield()
  33. bytesAfterYield %= yieldSize
  34. }
  35. bytesCopied += bytes
  36. bytesAfterYield += bytes
  37. }
  38. return@withContext bytesCopied
  39. }
  40. }