kotlinhttp-headersretrofitktorktor-client

Problem translating retrofit multipart call to ktor


Really stuck with translating multipart request from retrofit to ktor client.

In retrofit I have following method:

 @Multipart
 @POST("rest/sendPhotos")
 suspend fun sendPhotos(@Part files: List<MultipartBody.Part>): Response<ResultDto>

in datasource layer it's called as:

fun sendFiles(files: List<File>): Response<ResultDto> {
    val parts = mutableListOf<MultipartBody.Part>()
    files.forEachIndexed { index, file ->
        val requestFile = file.asRequestBody("multipart/form-items".toMediaTypeOrNull())
        val part = MultipartBody.Part.createFormData("image_$index", file.name, requestFile)
        parts.add(part)
    }
    return mainApiService.sendPhotos(parts)
}

In ktor I'm trying to translate it as:

    private suspend fun sendFiles(files: List<File>): HttpResponse {
        val parts = mutableListOf<PartData>()
        files.forEachIndexed { index, file ->
            val part = formData {
                append("content", InputProvider(file.length()) { file.inputStream().asInput() }, Headers.build {
                    append(HttpHeaders.ContentType, "multipart/form-items")
                    append(HttpHeaders.ContentDisposition, "filename=\"${file.name}\"; name=\"image_$index\"")
                })
            }
            parts.addAll(part)
        }
        return httpClient.post("rest/sendPhotos") {
            setBody(MultiPartFormDataContent(
                parts = parts,
            ))
        }
    }

But it doesn't work... Tried zillion variants, but helpless. Trying to fix it several days, unfortunately ktor logging can't help me, since it doesn't show body, printing smth like: [request body omitted]

Can anyone please help me? Any ideas or clues?

Added Retrofit logger reads:

Content-Type: multipart/form-data; boundary=0574af17-6a38-4888-af48-b368c4ce0f79
17:57:03.773  D  Content-Length: 209034
17:57:03.773  D  ticket: 00204e0d1669ccee81e6410390e48e530ba80c0c
17:57:03.788  D  
17:57:03.793  D  --0574af17-6a38-4888-af48-b368c4ce0f79
                 Content-Disposition: form-data; name="image_0"; filename="2024-01-03-00-56-48-232.jpg"
                 Content-Type: multipart/form-items
                 Content-Length: 208249

             

I can't get similar logs from ktor, it shows nothing except logs omitted - it's ugly...


Solution

  • According to the Retrofit logs, the equivalent Ktor code should be the following:

    client.post("rest/sendPhotos") {
        setBody(MultiPartFormDataContent(formData {
            files.forEachIndexed { index, file ->
                append("image_$index", file.readBytes(), Headers.build {
                    append(HttpHeaders.ContentType, "multipart/form-items")
                    append(HttpHeaders.ContentDisposition, "filename=\"${file.name}\"")
                })
            }
        }))
    }