Contexto:
Realizar una petición POST al siguiente servicio: https://badgecheck.io/results adjuntando una imagen, el servicio en cuestión validará si la imagen es un badge válido. Esta petición debe ser realizada con apache httpclient 5 https://hc.apache.org/httpcomponents-client-5.2.x/index.html y codificada en Kotlin.
Después de varios intentos fue posible realizarlo con el siguiente código:
@Throws(Exception::class)
fun executeFormMultipartPost(url: String, pathName: String) {
val client = HttpClients.createDefault()
val post = HttpPost(url)
post.addHeader("Accept", "application/json")
val builder = MultipartEntityBuilder.create()
builder.addBinaryBody(
"image", File(
object {}.javaClass.getResource(pathName).path
),
ContentType.IMAGE_PNG, "file"
)
builder.addTextBody("data", "")
post.entity = builder.build()
val response = client.execute(post)
println(EntityUtils.toString(response.entity))
}
fun main(args: Array<String>) {
println("Hello World!")
executeFormMultipartPostCustom(
url = "https://badgecheck.io/results",
pathName = "baked-badge-image.png"
)
}
El archivo baked-badge-image.png debe estar en la carpeta src/main/resources.

Las dependencias de httpclient 5 deben estar agregadas en el archivo build.gradle.kts
En caso de que se requiera obtener la imagen de una cadena de texto base64 el código solo varía un poco:
implementation("org.apache.httpcomponents.client5:httpclient5:5.2.1")
@Throws(Exception::class)
fun executeFormMultipartPostCustom(url: String, pathName: String) {
val client = HttpClients.createDefault()
val post = HttpPost(url)
post.addHeader("Accept", "application/json")
val decodedBytes = Base64.getDecoder().decode(getImageData())
val inputStreamBody: InputStreamBody = object : InputStreamBody(
ByteArrayInputStream(decodedBytes), ContentType.APPLICATION_OCTET_STREAM, "file") {
override fun getContentLength(): Long {
return decodedBytes.size.toLong()
}
}
val builder = MultipartEntityBuilder.create()
builder.addPart("image", inputStreamBody)
builder.addTextBody("data", "")
post.entity = builder.build()
val response = client.execute(post)
println(EntityUtils.toString(response.entity))
}
La imagen en Base64 deberia ser similar a:
fun getImageData(): String {
return "iVBORw...."
}
La respuesta debe lucir como:
{
"graph": [
{
"@context": "https://w3id.org/openbadges/v2",
"id": "https://api.badgr.io/public/assertions/hAbc4CzwR6i_Z7KKlsIN4g",
"type": "Assertion",
"image": "https://api.badgr.io/public/assertions/hAbc4CzwR6i_Z7KKlsIN4g/image",
"badge": "https://api.badgr.io/public/badges/0I52e1O8Rx-NMSKQoPcktg",
"issuedOn": "2019-04-11T19:13:34.545808+00:00",
"narrative": "Awarded by Badgr Pathways",
"recipient": {
"type": "email",
"hashed": true,
"identity": "sha256$0d3aff1333f840ba142c635ba6b0b2296aebaa0d86889adaa3d5577119e364e4",
"salt": "ed63e54c6f364ea9b7b4fa1acafc1251"
},
"verification": {
"type": "HostedBadge"
}
},
{
"@context": "https://w3id.org/openbadges/v2",
"id": "https://api.badgr.io/public/badges/0I52e1O8Rx-NMSKQoPcktg",
"type": "BadgeClass",
"description": "Turing game",
"image": "https://api.badgr.io/public/badges/0I52e1O8Rx-NMSKQoPcktg/image",
"tags": [],
"name": "Mastered Turning Game",
"alignment": [],
"criteria": {
"narrative": "Turing"
},
"issuer": "https://api.badgr.io/public/issuers/VSWDm7JjQmOX0ot5BtelLg"
},
{
"@context": "https://w3id.org/openbadges/v2",
"id": "https://api.badgr.io/public/issuers/VSWDm7JjQmOX0ot5BtelLg",
"type": "Issuer",
"description": "An interstellar federal republic, composed of planetary governments that agree to exist semi-autonomously under a single central government based on the principles of universal liberty, rights, and equality, and to share their knowledge and resources in peaceful cooperation, scientific development, space exploration and defensive purposes.",
"email": "yona@concentricsky.com",
"image": "https://api.badgr.io/public/issuers/VSWDm7JjQmOX0ot5BtelLg/image",
"name": "United Federation of Production Software",
"url": "http://badgr.io"
}
],
"input": {
"value": "https://api.badgr.io/public/assertions/hAbc4CzwR6i_Z7KKlsIN4g",
"input_type": "url"
},
"report": {
"validationSubject": "https://api.badgr.io/public/assertions/hAbc4CzwR6i_Z7KKlsIN4g",
"openBadgesVersion": "2.0",
"messages": [],
"errorCount": 0,
"warningCount": 0,
"valid": true
}
}