add uniupload for JVM

This commit is contained in:
InsanusMokrassar 2022-11-22 10:36:15 +06:00
parent b7b5159e9c
commit a3090cca9d
4 changed files with 102 additions and 4 deletions

View File

@ -1,15 +1,18 @@
package dev.inmo.micro_utils.ktor.client package dev.inmo.micro_utils.ktor.client
import dev.inmo.micro_utils.common.FileName import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.ktor.common.LambdaInputProvider
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.utils.io.core.Input import io.ktor.utils.io.core.Input
import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.StringFormat import kotlinx.serialization.StringFormat
import kotlinx.serialization.json.Json
data class UniUploadFileInfo( data class UniUploadFileInfo(
val fileName: FileName, val fileName: FileName,
val bytesAllocator: Input val mimeType: String,
val inputAllocator: LambdaInputProvider
) )
/** /**
@ -22,7 +25,7 @@ data class UniUploadFileInfo(
expect suspend fun <T> HttpClient.uniupload( expect suspend fun <T> HttpClient.uniupload(
url: String, url: String,
data: Map<String, Any>, data: Map<String, Any>,
stringFormat: StringFormat,
resultDeserializer: DeserializationStrategy<T>, resultDeserializer: DeserializationStrategy<T>,
headers: Headers = Headers.Empty headers: Headers = Headers.Empty,
stringFormat: StringFormat = Json.Default
): T? ): T?

View File

@ -4,6 +4,8 @@ import dev.inmo.micro_utils.common.MPPFile
import io.ktor.client.request.forms.InputProvider import io.ktor.client.request.forms.InputProvider
import io.ktor.utils.io.streams.asInput import io.ktor.utils.io.streams.asInput
actual suspend fun MPPFile.inputProvider(): InputProvider = InputProvider(length()) { fun MPPFile.inputProviderSync(): InputProvider = InputProvider(length()) {
inputStream().asInput() inputStream().asInput()
} }
actual suspend fun MPPFile.inputProvider(): InputProvider = inputProviderSync()

View File

@ -0,0 +1,88 @@
package dev.inmo.micro_utils.ktor.client
import dev.inmo.micro_utils.ktor.common.input
import io.ktor.client.HttpClient
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.statement.bodyAsText
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.Parameters
import io.ktor.http.content.PartData
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.StringFormat
import kotlinx.serialization.encodeToString
import kotlinx.serialization.serializer
import java.io.File
/**
* Will execute submitting of multipart data request
*
* @param data [Map] where keys will be used as names for multipart parts and values as values. If you will pass
* [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
*/
@OptIn(InternalSerializationApi::class)
actual suspend fun <T> HttpClient.uniupload(
url: String,
data: Map<String, Any>,
resultDeserializer: DeserializationStrategy<T>,
headers: Headers,
stringFormat: StringFormat
): T? {
val withBinary = data.values.any { it is File || it is UniUploadFileInfo }
val formData = formData {
data.forEach { (k, v) ->
when (v) {
is File -> append(
k,
v.inputProviderSync(),
Headers.build {
append(HttpHeaders.ContentType, v.mimeType)
append(HttpHeaders.ContentDisposition, "filename=\"${v.name}\"")
}
)
is UniUploadFileInfo -> append(
k,
InputProvider(block = v.inputAllocator),
Headers.build {
append(HttpHeaders.ContentType, v.mimeType)
append(HttpHeaders.ContentDisposition, "filename=\"${v.fileName.name}\"")
}
)
else -> append(
k,
stringFormat.encodeToString(v)
)
}
}
}
val response = if (withBinary) {
submitFormWithBinaryData(
url,
formData
)
} else {
submitForm(
url,
Parameters.build {
formData.forEach {
val formItem = (it as PartData.FormItem)
append(it.name!!, it.value)
}
}
)
}
return if (response.status == HttpStatusCode.OK) {
stringFormat.decodeFromString(resultDeserializer, response.bodyAsText())
} else {
null
}
}

View File

@ -0,0 +1,5 @@
package dev.inmo.micro_utils.ktor.common
import io.ktor.utils.io.core.Input
typealias LambdaInputProvider = () -> Input