add server part of uniUpload, fill changelog

This commit is contained in:
InsanusMokrassar 2022-11-22 13:38:36 +06:00
parent 844a129094
commit 2b5380f8d6
5 changed files with 63 additions and 29 deletions

View File

@ -2,6 +2,14 @@
## 0.14.3 ## 0.14.3
* `Common`:
* New type `Progress`
* `Ktor`:
* `Client`:
* New universal `uniUpload` extension for `HttpClient`
* `Server`:
* New universal `handleUniUpload` extension for `ApplicationCall`
## 0.14.2 ## 0.14.2
* `Versions`: * `Versions`:

View File

@ -21,7 +21,7 @@ data class UniUploadFileInfo(
* [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value
* in case you wish to pass other source of multipart binary data than regular file * in case you wish to pass other source of multipart binary data than regular file
*/ */
expect suspend fun <T> HttpClient.uniupload( expect suspend fun <T> HttpClient.uniUpload(
url: String, url: String,
data: Map<String, Any>, data: Map<String, Any>,
resultDeserializer: DeserializationStrategy<T>, resultDeserializer: DeserializationStrategy<T>,

View File

@ -25,7 +25,7 @@ import org.w3c.xhr.XMLHttpRequestResponseType
* [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value
* in case you wish to pass other source of multipart binary data than regular file * in case you wish to pass other source of multipart binary data than regular file
*/ */
actual suspend fun <T> HttpClient.uniupload( actual suspend fun <T> HttpClient.uniUpload(
url: String, url: String,
data: Map<String, Any>, data: Map<String, Any>,
resultDeserializer: DeserializationStrategy<T>, resultDeserializer: DeserializationStrategy<T>,
@ -55,6 +55,9 @@ actual suspend fun <T> HttpClient.uniupload(
} }
val request = XMLHttpRequest() val request = XMLHttpRequest()
headers.forEach { s, strings ->
request.setRequestHeader(s, strings.joinToString())
}
request.responseType = XMLHttpRequestResponseType.TEXT request.responseType = XMLHttpRequestResponseType.TEXT
request.upload.onprogress = { request.upload.onprogress = {
onUpload(it.loaded.toLong(), it.total.toLong()) onUpload(it.loaded.toLong(), it.total.toLong())

View File

@ -2,11 +2,14 @@ package dev.inmo.micro_utils.ktor.client
import dev.inmo.micro_utils.common.Progress import dev.inmo.micro_utils.common.Progress
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.mergeHeaders
import io.ktor.client.plugins.onUpload import io.ktor.client.plugins.onUpload
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.InputProvider import io.ktor.client.request.forms.InputProvider
import io.ktor.client.request.forms.formData import io.ktor.client.request.forms.formData
import io.ktor.client.request.forms.submitForm import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.forms.submitFormWithBinaryData import io.ktor.client.request.forms.submitFormWithBinaryData
import io.ktor.client.request.headers
import io.ktor.client.statement.bodyAsText import io.ktor.client.statement.bodyAsText
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders
@ -25,7 +28,7 @@ import java.io.File
* [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value
* in case you wish to pass other source of multipart binary data than regular file * in case you wish to pass other source of multipart binary data than regular file
*/ */
actual suspend fun <T> HttpClient.uniupload( actual suspend fun <T> HttpClient.uniUpload(
url: String, url: String,
data: Map<String, Any>, data: Map<String, Any>,
resultDeserializer: DeserializationStrategy<T>, resultDeserializer: DeserializationStrategy<T>,
@ -62,15 +65,21 @@ actual suspend fun <T> HttpClient.uniupload(
} }
} }
val requestBuilder: HttpRequestBuilder.() -> Unit = {
headers {
appendAll(headers)
}
onUpload { bytesSentTotal, contentLength ->
onUpload(bytesSentTotal, contentLength)
}
}
val response = if (withBinary) { val response = if (withBinary) {
submitFormWithBinaryData( submitFormWithBinaryData(
url, url,
formData formData,
) { block = requestBuilder
onUpload { bytesSentTotal, contentLength -> )
onUpload(bytesSentTotal, contentLength)
}
}
} else { } else {
submitForm( submitForm(
url, url,
@ -79,12 +88,9 @@ actual suspend fun <T> HttpClient.uniupload(
val formItem = (it as PartData.FormItem) val formItem = (it as PartData.FormItem)
append(it.name!!, it.value) append(it.name!!, it.value)
} }
} },
) { block = requestBuilder
onUpload { bytesSentTotal, contentLength -> )
onUpload(bytesSentTotal, contentLength)
}
}
} }
return if (response.status == HttpStatusCode.OK) { return if (response.status == HttpStatusCode.OK) {

View File

@ -7,29 +7,46 @@ import io.ktor.server.application.ApplicationCall
import io.ktor.server.request.receiveMultipart import io.ktor.server.request.receiveMultipart
import io.ktor.utils.io.core.* import io.ktor.utils.io.core.*
/**
* Server-side part which receives [dev.inmo.micro_utils.ktor.client.uniUpload] request
*/
suspend fun ApplicationCall.handleUniUpload(
onFormItem: (PartData.FormItem) -> Unit = {},
onFileItem: (PartData.FileItem) -> Unit = {},
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
) {
val multipartData = receiveMultipart()
multipartData.forEachPart {
when (it) {
is PartData.FormItem -> onFormItem(it)
is PartData.FileItem -> onFileItem(it)
is PartData.BinaryItem -> onBinaryContent(it)
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
}
}
}
suspend fun ApplicationCall.uniloadMultipart( suspend fun ApplicationCall.uniloadMultipart(
onFormItem: (PartData.FormItem) -> Unit = {}, onFormItem: (PartData.FormItem) -> Unit = {},
onCustomFileItem: (PartData.FileItem) -> Unit = {}, onCustomFileItem: (PartData.FileItem) -> Unit = {},
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {}, onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
onBinaryContent: (PartData.BinaryItem) -> Unit = {} onBinaryContent: (PartData.BinaryItem) -> Unit = {}
) = safely { ) = safely {
val multipartData = receiveMultipart()
var resultInput: Input? = null var resultInput: Input? = null
multipartData.forEachPart { handleUniUpload(
when (it) { onFormItem,
is PartData.FormItem -> onFormItem(it) {
is PartData.FileItem -> { when (it.name) {
when (it.name) { "bytes" -> resultInput = it.provider()
"bytes" -> resultInput = it.provider() else -> onCustomFileItem(it)
else -> onCustomFileItem(it)
}
} }
is PartData.BinaryItem -> onBinaryContent(it) },
is PartData.BinaryChannelItem -> onBinaryChannelItem(it) onBinaryChannelItem,
} onBinaryContent
} )
resultInput ?: error("Bytes has not been received") resultInput ?: error("Bytes has not been received")
} }