mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	add server part of uniUpload, fill changelog
This commit is contained in:
		@@ -2,6 +2,14 @@
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
 | 
			
		||||
* `Versions`:
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 * 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,
 | 
			
		||||
    data: Map<String, Any>,
 | 
			
		||||
    resultDeserializer: DeserializationStrategy<T>,
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 * 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,
 | 
			
		||||
    data: Map<String, Any>,
 | 
			
		||||
    resultDeserializer: DeserializationStrategy<T>,
 | 
			
		||||
@@ -55,6 +55,9 @@ actual suspend fun <T> HttpClient.uniupload(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val request = XMLHttpRequest()
 | 
			
		||||
    headers.forEach { s, strings ->
 | 
			
		||||
        request.setRequestHeader(s, strings.joinToString())
 | 
			
		||||
    }
 | 
			
		||||
    request.responseType = XMLHttpRequestResponseType.TEXT
 | 
			
		||||
    request.upload.onprogress = {
 | 
			
		||||
        onUpload(it.loaded.toLong(), it.total.toLong())
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,14 @@ package dev.inmo.micro_utils.ktor.client
 | 
			
		||||
 | 
			
		||||
import dev.inmo.micro_utils.common.Progress
 | 
			
		||||
import io.ktor.client.HttpClient
 | 
			
		||||
import io.ktor.client.engine.mergeHeaders
 | 
			
		||||
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.formData
 | 
			
		||||
import io.ktor.client.request.forms.submitForm
 | 
			
		||||
import io.ktor.client.request.forms.submitFormWithBinaryData
 | 
			
		||||
import io.ktor.client.request.headers
 | 
			
		||||
import io.ktor.client.statement.bodyAsText
 | 
			
		||||
import io.ktor.http.Headers
 | 
			
		||||
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
 | 
			
		||||
 * 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,
 | 
			
		||||
    data: Map<String, Any>,
 | 
			
		||||
    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) {
 | 
			
		||||
        submitFormWithBinaryData(
 | 
			
		||||
            url,
 | 
			
		||||
            formData
 | 
			
		||||
        ) {
 | 
			
		||||
            onUpload { bytesSentTotal, contentLength ->
 | 
			
		||||
                onUpload(bytesSentTotal, contentLength)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
            formData,
 | 
			
		||||
            block = requestBuilder
 | 
			
		||||
        )
 | 
			
		||||
    } else {
 | 
			
		||||
        submitForm(
 | 
			
		||||
            url,
 | 
			
		||||
@@ -79,12 +88,9 @@ actual suspend fun <T> HttpClient.uniupload(
 | 
			
		||||
                    val formItem = (it as PartData.FormItem)
 | 
			
		||||
                    append(it.name!!, it.value)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        ) {
 | 
			
		||||
            onUpload { bytesSentTotal, contentLength ->
 | 
			
		||||
                onUpload(bytesSentTotal, contentLength)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
            },
 | 
			
		||||
            block = requestBuilder
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return if (response.status == HttpStatusCode.OK) {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,29 +7,46 @@ import io.ktor.server.application.ApplicationCall
 | 
			
		||||
import io.ktor.server.request.receiveMultipart
 | 
			
		||||
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(
 | 
			
		||||
    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
			
		||||
    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
			
		||||
    onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
 | 
			
		||||
    onBinaryContent: (PartData.BinaryItem) -> Unit = {}
 | 
			
		||||
) = safely {
 | 
			
		||||
    val multipartData = receiveMultipart()
 | 
			
		||||
 | 
			
		||||
    var resultInput: Input? = null
 | 
			
		||||
 | 
			
		||||
    multipartData.forEachPart {
 | 
			
		||||
        when (it) {
 | 
			
		||||
            is PartData.FormItem -> onFormItem(it)
 | 
			
		||||
            is PartData.FileItem -> {
 | 
			
		||||
                when (it.name) {
 | 
			
		||||
                    "bytes" -> resultInput = it.provider()
 | 
			
		||||
                    else -> onCustomFileItem(it)
 | 
			
		||||
                }
 | 
			
		||||
    handleUniUpload(
 | 
			
		||||
        onFormItem,
 | 
			
		||||
        {
 | 
			
		||||
            when (it.name) {
 | 
			
		||||
                "bytes" -> resultInput = it.provider()
 | 
			
		||||
                else -> onCustomFileItem(it)
 | 
			
		||||
            }
 | 
			
		||||
            is PartData.BinaryItem -> onBinaryContent(it)
 | 
			
		||||
            is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        },
 | 
			
		||||
        onBinaryChannelItem,
 | 
			
		||||
        onBinaryContent
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    resultInput ?: error("Bytes has not been received")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user