mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-15 13:29:38 +00:00
experimentally add linuxx64 and mingwx64 as target platforms
This commit is contained in:
@@ -18,5 +18,17 @@ kotlin {
|
||||
androidMain {
|
||||
dependsOn jvmMain
|
||||
}
|
||||
|
||||
linuxX64Main {
|
||||
dependencies {
|
||||
api internalProject("micro_utils.mime_types")
|
||||
}
|
||||
}
|
||||
|
||||
mingwX64Main {
|
||||
dependencies {
|
||||
api internalProject("micro_utils.mime_types")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,10 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.filesize
|
||||
import dev.inmo.micro_utils.ktor.common.input
|
||||
import io.ktor.client.request.forms.InputProvider
|
||||
|
||||
expect suspend fun MPPFile.inputProvider(): InputProvider
|
||||
fun MPPFile.inputProvider(): InputProvider = InputProvider(filesize) {
|
||||
input()
|
||||
}
|
||||
|
@@ -1,11 +0,0 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.*
|
||||
import io.ktor.client.request.forms.InputProvider
|
||||
import io.ktor.utils.io.core.ByteReadPacket
|
||||
|
||||
actual suspend fun MPPFile.inputProvider(): InputProvider = bytes().let {
|
||||
InputProvider(it.size.toLong()) {
|
||||
ByteReadPacket(it)
|
||||
}
|
||||
}
|
@@ -7,5 +7,3 @@ import io.ktor.utils.io.streams.asInput
|
||||
fun MPPFile.inputProviderSync(): InputProvider = InputProvider(length()) {
|
||||
inputStream().asInput()
|
||||
}
|
||||
|
||||
actual suspend fun MPPFile.inputProvider(): InputProvider = inputProviderSync()
|
||||
|
40
ktor/client/src/linuxX64Main/kotlin/ActualTemporalUpload.kt
Normal file
40
ktor/client/src/linuxX64Main/kotlin/ActualTemporalUpload.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.filename
|
||||
import dev.inmo.micro_utils.ktor.common.TemporalFileId
|
||||
import dev.inmo.micro_utils.mime_types.getMimeTypeOrAny
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.plugins.onUpload
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.forms.submitFormWithBinaryData
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
|
||||
internal val MPPFile.mimeType: String
|
||||
get() = getMimeTypeOrAny(filename.extension).raw
|
||||
|
||||
actual suspend fun HttpClient.tempUpload(
|
||||
fullTempUploadDraftPath: String,
|
||||
file: MPPFile,
|
||||
onUpload: OnUploadCallback
|
||||
): TemporalFileId {
|
||||
val inputProvider = file.inputProvider()
|
||||
val fileId = submitFormWithBinaryData(
|
||||
fullTempUploadDraftPath,
|
||||
formData = formData {
|
||||
append(
|
||||
"data",
|
||||
inputProvider,
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, file.mimeType)
|
||||
append(HttpHeaders.ContentDisposition, "filename=\"${file.filename.string}\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
onUpload(onUpload)
|
||||
}.bodyAsText()
|
||||
return TemporalFileId(fileId)
|
||||
}
|
107
ktor/client/src/linuxX64Main/kotlin/ActualUniUpload.kt
Normal file
107
ktor/client/src/linuxX64Main/kotlin/ActualUniUpload.kt
Normal file
@@ -0,0 +1,107 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
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
|
||||
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.SerializationStrategy
|
||||
import kotlinx.serialization.StringFormat
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.serializer
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @suppress
|
||||
*/
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
actual suspend fun <T> HttpClient.uniUpload(
|
||||
url: String,
|
||||
data: Map<String, Any>,
|
||||
resultDeserializer: DeserializationStrategy<T>,
|
||||
headers: Headers,
|
||||
stringFormat: StringFormat,
|
||||
onUpload: OnUploadCallback
|
||||
): T? {
|
||||
val withBinary = data.values.any { it is MPPFile || it is UniUploadFileInfo }
|
||||
|
||||
val formData = formData {
|
||||
for (k in data.keys) {
|
||||
val v = data[k] ?: continue
|
||||
when (v) {
|
||||
is MPPFile -> append(
|
||||
k,
|
||||
v.inputProvider(),
|
||||
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::class.serializer() as SerializationStrategy<in Any>, v)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val requestBuilder: HttpRequestBuilder.() -> Unit = {
|
||||
headers {
|
||||
appendAll(headers)
|
||||
}
|
||||
onUpload { bytesSentTotal, contentLength ->
|
||||
onUpload(bytesSentTotal, contentLength)
|
||||
}
|
||||
}
|
||||
|
||||
val response = if (withBinary) {
|
||||
submitFormWithBinaryData(
|
||||
url,
|
||||
formData,
|
||||
block = requestBuilder
|
||||
)
|
||||
} else {
|
||||
submitForm(
|
||||
url,
|
||||
Parameters.build {
|
||||
for (it in formData) {
|
||||
val formItem = (it as PartData.FormItem)
|
||||
append(it.name!!, it.value)
|
||||
}
|
||||
},
|
||||
block = requestBuilder
|
||||
)
|
||||
}
|
||||
|
||||
return if (response.status == HttpStatusCode.OK) {
|
||||
stringFormat.decodeFromString(resultDeserializer, response.bodyAsText())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
40
ktor/client/src/mingwX64Main/kotlin/ActualTemporalUpload.kt
Normal file
40
ktor/client/src/mingwX64Main/kotlin/ActualTemporalUpload.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.filename
|
||||
import dev.inmo.micro_utils.ktor.common.TemporalFileId
|
||||
import dev.inmo.micro_utils.mime_types.getMimeTypeOrAny
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.plugins.onUpload
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.forms.submitFormWithBinaryData
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
|
||||
internal val MPPFile.mimeType: String
|
||||
get() = getMimeTypeOrAny(filename.extension).raw
|
||||
|
||||
actual suspend fun HttpClient.tempUpload(
|
||||
fullTempUploadDraftPath: String,
|
||||
file: MPPFile,
|
||||
onUpload: OnUploadCallback
|
||||
): TemporalFileId {
|
||||
val inputProvider = file.inputProvider()
|
||||
val fileId = submitFormWithBinaryData(
|
||||
fullTempUploadDraftPath,
|
||||
formData = formData {
|
||||
append(
|
||||
"data",
|
||||
inputProvider,
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, file.mimeType)
|
||||
append(HttpHeaders.ContentDisposition, "filename=\"${file.filename.string}\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
onUpload(onUpload)
|
||||
}.bodyAsText()
|
||||
return TemporalFileId(fileId)
|
||||
}
|
107
ktor/client/src/mingwX64Main/kotlin/ActualUniUpload.kt
Normal file
107
ktor/client/src/mingwX64Main/kotlin/ActualUniUpload.kt
Normal file
@@ -0,0 +1,107 @@
|
||||
package dev.inmo.micro_utils.ktor.client
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
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
|
||||
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.SerializationStrategy
|
||||
import kotlinx.serialization.StringFormat
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.serializer
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @suppress
|
||||
*/
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
actual suspend fun <T> HttpClient.uniUpload(
|
||||
url: String,
|
||||
data: Map<String, Any>,
|
||||
resultDeserializer: DeserializationStrategy<T>,
|
||||
headers: Headers,
|
||||
stringFormat: StringFormat,
|
||||
onUpload: OnUploadCallback
|
||||
): T? {
|
||||
val withBinary = data.values.any { it is MPPFile || it is UniUploadFileInfo }
|
||||
|
||||
val formData = formData {
|
||||
for (k in data.keys) {
|
||||
val v = data[k] ?: continue
|
||||
when (v) {
|
||||
is MPPFile -> append(
|
||||
k,
|
||||
v.inputProvider(),
|
||||
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::class.serializer() as SerializationStrategy<in Any>, v)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val requestBuilder: HttpRequestBuilder.() -> Unit = {
|
||||
headers {
|
||||
appendAll(headers)
|
||||
}
|
||||
onUpload { bytesSentTotal, contentLength ->
|
||||
onUpload(bytesSentTotal, contentLength)
|
||||
}
|
||||
}
|
||||
|
||||
val response = if (withBinary) {
|
||||
submitFormWithBinaryData(
|
||||
url,
|
||||
formData,
|
||||
block = requestBuilder
|
||||
)
|
||||
} else {
|
||||
submitForm(
|
||||
url,
|
||||
Parameters.build {
|
||||
for (it in formData) {
|
||||
val formItem = (it as PartData.FormItem)
|
||||
append(it.name!!, it.value)
|
||||
}
|
||||
},
|
||||
block = requestBuilder
|
||||
)
|
||||
}
|
||||
|
||||
return if (response.status == HttpStatusCode.OK) {
|
||||
stringFormat.decodeFromString(resultDeserializer, response.bodyAsText())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
33
ktor/common/src/linuxX64Main/kotlin/ActualMPPFileInput.kt
Normal file
33
ktor/common/src/linuxX64Main/kotlin/ActualMPPFileInput.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package dev.inmo.micro_utils.ktor.common
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import io.ktor.utils.io.bits.Memory
|
||||
import io.ktor.utils.io.bits.loadByteArray
|
||||
import io.ktor.utils.io.core.Input
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
|
||||
private class FileInput(
|
||||
private val path: Path
|
||||
) : Input() {
|
||||
private val openedFile = FileSystem.SYSTEM.openReadOnly(path)
|
||||
override fun closeSource() {
|
||||
openedFile.close()
|
||||
}
|
||||
|
||||
override fun fill(destination: Memory, offset: Int, length: Int): Int {
|
||||
val byteArray = ByteArray(length)
|
||||
val read = openedFile.read(offset.toLong(), byteArray, 0, length)
|
||||
destination.loadByteArray(
|
||||
offset,
|
||||
byteArray,
|
||||
count = length
|
||||
)
|
||||
return read
|
||||
}
|
||||
}
|
||||
|
||||
actual fun MPPFile.input(): Input {
|
||||
return FileInput(this)
|
||||
}
|
||||
|
33
ktor/common/src/mingwX64Main/kotlin/ActualMPPFileInput.kt
Normal file
33
ktor/common/src/mingwX64Main/kotlin/ActualMPPFileInput.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package dev.inmo.micro_utils.ktor.common
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import io.ktor.utils.io.bits.Memory
|
||||
import io.ktor.utils.io.bits.loadByteArray
|
||||
import io.ktor.utils.io.core.Input
|
||||
import okio.FileSystem
|
||||
import okio.Path
|
||||
|
||||
private class FileInput(
|
||||
private val path: Path
|
||||
) : Input() {
|
||||
private val openedFile = FileSystem.SYSTEM.openReadOnly(path)
|
||||
override fun closeSource() {
|
||||
openedFile.close()
|
||||
}
|
||||
|
||||
override fun fill(destination: Memory, offset: Int, length: Int): Int {
|
||||
val byteArray = ByteArray(length)
|
||||
val read = openedFile.read(offset.toLong(), byteArray, 0, length)
|
||||
destination.loadByteArray(
|
||||
offset,
|
||||
byteArray,
|
||||
count = length
|
||||
)
|
||||
return read
|
||||
}
|
||||
}
|
||||
|
||||
actual fun MPPFile.input(): Input {
|
||||
return FileInput(this)
|
||||
}
|
||||
|
Reference in New Issue
Block a user