[kotlin][client] fix file upload with okhttp (#13435)

* [kotlin][client] fix file upload with okhttp

* [kotlin][client] fix file upload with okhttp

* [kotlin][client] update sample projects

* [kotlin][client] fix file upload with okhttp3

* [kotlin][client] update sample projects
This commit is contained in:
Bruno Coelho 2022-09-17 15:08:07 +01:00 committed by GitHub
parent 863dbc7c3e
commit b9d71581dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 358 additions and 278 deletions

View File

@ -116,6 +116,12 @@ import com.squareup.moshi.adapter
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
{{#jvm-okhttp3}}
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
{{/jvm-okhttp3}}
{{#jvm-okhttp4}}
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
{{/jvm-okhttp4}}
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -123,27 +129,41 @@ import com.squareup.moshi.adapter
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + {{#jvm-okhttp3}}
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") val fileMediaType = MediaType.parse(guessContentTypeFromFile(part.body))
addPart({{#jvm-okhttp3}}Headers.of(headers){{/jvm-okhttp3}}{{#jvm-okhttp4}}headers.toHeaders(){{/jvm-okhttp4}}, addPart(
requestSingleBody(body, contentType)) Headers.of(partHeaders),
RequestBody.create(fileMediaType, part.body)
)
{{/jvm-okhttp3}}
{{#jvm-okhttp4}}
val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
addPart(
partHeaders.toHeaders(),
part.body.asRequestBody(fileMediaType)
)
{{/jvm-okhttp4}}
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
{{#jvm-okhttp3}}
addPart(
Headers.of(partHeaders),
RequestBody.create(null, parameterToString(part.body))
)
{{/jvm-okhttp3}}
{{#jvm-okhttp4}}
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
{{/jvm-okhttp4}}
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
{{#jvm-okhttp3}}
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
{{/jvm-okhttp3}}
{{#jvm-okhttp4}}
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
{{/jvm-okhttp4}}
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -65,6 +65,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -72,22 +73,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = MediaType.parse(guessContentTypeFromFile(part.body))
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(Headers.of(headers), Headers.of(partHeaders),
requestSingleBody(body, contentType)) RequestBody.create(fileMediaType, part.body)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
Headers.of(partHeaders),
RequestBody.create(null, parameterToString(part.body))
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -65,6 +65,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -72,22 +73,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = MediaType.parse(guessContentTypeFromFile(part.body))
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(Headers.of(headers), Headers.of(partHeaders),
requestSingleBody(body, contentType)) RequestBody.create(fileMediaType, part.body)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
Headers.of(partHeaders),
RequestBody.create(null, parameterToString(part.body))
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -70,6 +70,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -77,22 +78,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -71,6 +71,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -78,22 +79,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ internal open class ApiClient(val baseUrl: String, val client: OkHttpClient = de
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ internal open class ApiClient(val baseUrl: String, val client: OkHttpClient = de
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -65,6 +65,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -72,22 +73,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = MediaType.parse(guessContentTypeFromFile(part.body))
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(Headers.of(headers), Headers.of(partHeaders),
requestSingleBody(body, contentType)) RequestBody.create(fileMediaType, part.body)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
Headers.of(partHeaders),
RequestBody.create(null, parameterToString(part.body))
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> RequestBody.create(MediaType.parse(mediaType ?: guessContentTypeFromFile(content)), content)
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -69,6 +69,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -76,22 +77,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>

View File

@ -68,6 +68,7 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody = protected inline fun <reified T> requestBody(content: T, mediaType: String?): RequestBody =
when { when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormDataMediaType -> mediaType == FormDataMediaType ->
MultipartBody.Builder() MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
@ -75,22 +76,24 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
(content as Map<String, PartConfig<*>>).forEach { (name, part) -> (content as Map<String, PartConfig<*>>).forEach { (name, part) ->
val contentType = part.headers.remove("Content-Type") if (part.body is File) {
val bodies = if (part.body is Iterable<*>) part.body else listOf(part.body) val partHeaders = part.headers.toMutableMap() +
bodies.forEach { body -> ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"")
val headers = part.headers.toMutableMap() + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull()
("Content-Disposition" to "form-data; name=\"$name\"" + if (body is File) "; filename=\"${body.name}\"" else "") addPart(
addPart(headers.toHeaders(), partHeaders.toHeaders(),
requestSingleBody(body, contentType)) part.body.asRequestBody(fileMediaType)
)
} else {
val partHeaders = part.headers.toMutableMap() +
("Content-Disposition" to "form-data; name=\"$name\"")
addPart(
partHeaders.toHeaders(),
parameterToString(part.body).toRequestBody(null)
)
} }
} }
}.build() }.build()
else -> requestSingleBody(content, mediaType)
}
protected inline fun <reified T> requestSingleBody(content: T, mediaType: String?): RequestBody =
when {
content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
mediaType == FormUrlEncMediaType -> { mediaType == FormUrlEncMediaType -> {
FormBody.Builder().apply { FormBody.Builder().apply {
// content's type *must* be Map<String, PartConfig<*>> // content's type *must* be Map<String, PartConfig<*>>