[kotlin] [multiplatform] [jvm-ktor] Fix formdata file upload (#21056)

* fix: kotlin multiplatform form-data file upload

* generate samples

* fix form data binary for jvm-ktor
This commit is contained in:
Julian Kalinowski 2025-04-25 10:30:25 +02:00 committed by GitHub
parent be77442bff
commit f9dedd74ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 30 additions and 26 deletions

View File

@ -1021,7 +1021,11 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
if ((JVM_KTOR.equals(getLibrary()) || MULTIPLATFORM.equals(getLibrary())) && operation.allParams != null) {
for (CodegenParameter param : operation.allParams) {
if (param.dataFormat != null && param.dataFormat.equals("binary")) {
param.baseType = param.dataType = "io.ktor.client.request.forms.InputProvider";
if (param.isContainer) {
param.baseType = param.dataType = typeMapping.get(collectionType) + "<io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>>";
} else {
param.baseType = param.dataType = "io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>";
}
}
}
}

View File

@ -63,7 +63,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
formData {
{{#formParams}}
{{#isFile}}
{{{paramName}}}?.apply { append("{{{baseName}}}", {{{paramName}}}) }
{{{paramName}}}?.apply { append({{{paramName}}}) }
{{/isFile}}
{{^isFile}}
{{^isArray}}
@ -81,7 +81,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
{{/isArray}}
{{#isArray}}
for (x in {{paramName}} ?: listOf()) {
append("{{{baseName}}}", x.toString())
{{#isFile}}append(it){{/isFile}}{{^isFile}}append("{{{baseName}}}", x.toString()){{/isFile}}
}
{{/isArray}}
{{/isFile}}

View File

@ -76,11 +76,11 @@ import kotlinx.serialization.encoding.*
{{#formParams}}
{{#isArray}}
{{{paramName}}}?.onEach {
append("{{{baseName}}}[]", it)
{{#isFile}}append(it){{/isFile}}{{^isFile}}append("{{{baseName}}}", it){{/isFile}}
}
{{/isArray}}
{{^isArray}}
{{{paramName}}}?.apply { append("{{{baseName}}}", {{^isEnumOrRef}}{{{paramName}}}{{/isEnumOrRef}}{{#isEnumOrRef}}{{{paramName}}}.value{{/isEnumOrRef}}) }
{{{paramName}}}?.apply { {{#isFile}}append({{{baseName}}}){{/isFile}}{{^isFile}}append("{{{baseName}}}", {{^isEnumOrRef}}{{{paramName}}}{{/isEnumOrRef}}{{#isEnumOrRef}}{{{paramName}}}.value{{/isEnumOrRef}}){{/isFile}} }
{{/isArray}}
{{/formParams}}
}

View File

@ -90,7 +90,7 @@ open class DefaultApi : ApiClient {
fn2?.apply { append("fn2", fn2) }
fn3?.apply { append("fn3", fn3) }
fn4?.onEach {
append("fn4[]", it)
append("fn4", it)
}
}

View File

@ -360,7 +360,7 @@ uploads an image
val apiInstance = PetApi()
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : io.ktor.client.request.forms.InputProvider = BINARY_DATA_HERE // io.ktor.client.request.forms.InputProvider | file to upload
val file : io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> = BINARY_DATA_HERE // io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> | file to upload
try {
val result : ModelApiResponse = apiInstance.uploadFile(petId, additionalMetadata, file)
println(result)
@ -378,7 +378,7 @@ try {
| **additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional] |
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **file** | **io.ktor.client.request.forms.InputProvider**| file to upload | [optional] |
| **file** | **io.ktor.client.request.forms.FormPart&lt;io.ktor.client.request.forms.InputProvider&gt;**| file to upload | [optional] |
### Return type

View File

@ -290,14 +290,14 @@ import java.text.DateFormat
* @return ModelApiResponse
*/
@Suppress("UNCHECKED_CAST")
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.InputProvider?): HttpResponse<ModelApiResponse> {
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>?): HttpResponse<ModelApiResponse> {
val localVariableAuthNames = listOf<String>("petstore_auth")
val localVariableBody =
formData {
additionalMetadata?.apply { append("additionalMetadata", additionalMetadata) }
file?.apply { append("file", file) }
file?.apply { append(file) }
}
val localVariableQuery = mutableMapOf<String, List<String>>()

View File

@ -360,7 +360,7 @@ uploads an image
val apiInstance = PetApi()
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : io.ktor.client.request.forms.InputProvider = BINARY_DATA_HERE // io.ktor.client.request.forms.InputProvider | file to upload
val file : io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> = BINARY_DATA_HERE // io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> | file to upload
try {
val result : ModelApiResponse = apiInstance.uploadFile(petId, additionalMetadata, file)
println(result)
@ -378,7 +378,7 @@ try {
| **additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional] |
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **file** | **io.ktor.client.request.forms.InputProvider**| file to upload | [optional] |
| **file** | **io.ktor.client.request.forms.FormPart&lt;io.ktor.client.request.forms.InputProvider&gt;**| file to upload | [optional] |
### Return type

View File

@ -288,14 +288,14 @@ import com.fasterxml.jackson.databind.ObjectMapper
* @return ModelApiResponse
*/
@Suppress("UNCHECKED_CAST")
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.InputProvider?): HttpResponse<ModelApiResponse> {
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>?): HttpResponse<ModelApiResponse> {
val localVariableAuthNames = listOf<String>("petstore_auth")
val localVariableBody =
formData {
additionalMetadata?.apply { append("additionalMetadata", additionalMetadata) }
file?.apply { append("file", file) }
file?.apply { append(file) }
}
val localVariableQuery = mutableMapOf<String, List<String>>()

View File

@ -372,7 +372,7 @@ uploads an image
val apiInstance = PetApi()
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : io.ktor.client.request.forms.InputProvider = BINARY_DATA_HERE // io.ktor.client.request.forms.InputProvider | file to upload
val file : io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> = BINARY_DATA_HERE // io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> | file to upload
try {
val result : ModelApiResponse = apiInstance.uploadFile(petId, additionalMetadata, file)
println(result)
@ -390,7 +390,7 @@ try {
| **additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional] |
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **file** | **io.ktor.client.request.forms.InputProvider**| file to upload | [optional] |
| **file** | **io.ktor.client.request.forms.FormPart&lt;io.ktor.client.request.forms.InputProvider&gt;**| file to upload | [optional] |
### Return type

View File

@ -287,14 +287,14 @@ import io.ktor.http.ParametersBuilder
* @return ModelApiResponse
*/
@Suppress("UNCHECKED_CAST")
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.InputProvider?): HttpResponse<ModelApiResponse> {
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String?, file: io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>?): HttpResponse<ModelApiResponse> {
val localVariableAuthNames = listOf<String>("petstore_auth")
val localVariableBody =
formData {
additionalMetadata?.apply { append("additionalMetadata", additionalMetadata) }
file?.apply { append("file", file) }
file?.apply { append(file) }
}
val localVariableQuery = mutableMapOf<String, List<String>>()

View File

@ -360,7 +360,7 @@ uploads an image
val apiInstance = PetApi()
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : io.ktor.client.request.forms.InputProvider = BINARY_DATA_HERE // io.ktor.client.request.forms.InputProvider | file to upload
val file : io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> = BINARY_DATA_HERE // io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> | file to upload
try {
val result : ModelApiResponse = apiInstance.uploadFile(petId, additionalMetadata, file)
println(result)
@ -378,7 +378,7 @@ try {
| **additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional] |
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **file** | **io.ktor.client.request.forms.InputProvider**| file to upload | [optional] |
| **file** | **io.ktor.client.request.forms.FormPart&lt;io.ktor.client.request.forms.InputProvider&gt;**| file to upload | [optional] |
### Return type

View File

@ -324,14 +324,14 @@ open class PetApi : ApiClient {
* @return ModelApiResponse
*/
@Suppress("UNCHECKED_CAST")
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String? = null, file: io.ktor.client.request.forms.InputProvider? = null): HttpResponse<ModelApiResponse> {
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String? = null, file: io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>? = null): HttpResponse<ModelApiResponse> {
val localVariableAuthNames = listOf<String>("petstore_auth")
val localVariableBody =
formData {
additionalMetadata?.apply { append("additionalMetadata", additionalMetadata) }
file?.apply { append("file", file) }
file?.apply { append(file) }
}
val localVariableQuery = mutableMapOf<String, List<String>>()

View File

@ -360,7 +360,7 @@ uploads an image
val apiInstance = PetApi()
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : io.ktor.client.request.forms.InputProvider = BINARY_DATA_HERE // io.ktor.client.request.forms.InputProvider | file to upload
val file : io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> = BINARY_DATA_HERE // io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider> | file to upload
try {
val result : ModelApiResponse = apiInstance.uploadFile(petId, additionalMetadata, file)
println(result)
@ -378,7 +378,7 @@ try {
| **additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional] |
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **file** | **io.ktor.client.request.forms.InputProvider**| file to upload | [optional] |
| **file** | **io.ktor.client.request.forms.FormPart&lt;io.ktor.client.request.forms.InputProvider&gt;**| file to upload | [optional] |
### Return type

View File

@ -324,14 +324,14 @@ open class PetApi : ApiClient {
* @return ModelApiResponse
*/
@Suppress("UNCHECKED_CAST")
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String? = null, file: io.ktor.client.request.forms.InputProvider? = null): HttpResponse<ModelApiResponse> {
open suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String? = null, file: io.ktor.client.request.forms.FormPart<io.ktor.client.request.forms.InputProvider>? = null): HttpResponse<ModelApiResponse> {
val localVariableAuthNames = listOf<String>("petstore_auth")
val localVariableBody =
formData {
additionalMetadata?.apply { append("additionalMetadata", additionalMetadata) }
file?.apply { append("file", file) }
file?.apply { append(file) }
}
val localVariableQuery = mutableMapOf<String, List<String>>()