You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android下Ktor Client多部分表单POST请求返回格式错误排查

Android中Ktor Client调用Stability API的400错误解决

问题场景

在Android项目中使用Ktor Client调用Stability API生成图片,初始实现代码如下:

suspend fun generateImageOfText(text: String,aspectRatio: String = "1:1", apiKey: String): Result {
    return try {
        val response = httpClient.post("https://api.stability.ai/v2beta/stable-image/generate/ultra") {
            header(HttpHeaders.Authorization, "Bearer $apiKey")
            header(HttpHeaders.Accept, "application/json")
            setBody(MultiPartFormDataContent(
                formData {
                    append("prompt", text)
                },
                boundary = "WebAppBoundary"
            ))
        }
        val resultText = response.bodyAsText()
        Log.d("APIConnector", "generateImageOfText: status ${response.status} result $resultText")
        Result.Success(resultText)
    }catch (e: Exception){
        e.printStackTrace()
        (Result.Error(e.message ?: "Unknown error"))
    }
}

错误反馈

请求返回400 Bad Request,错误详情:

400 Bad Request response {"success":false,"message":"Malformed FormData request. Content-Disposition header in FormData part is missing a name."}

尝试过程

Stability API要求使用多部分表单数据提交请求,参考官方上传图片的示例代码(如下),但我的场景仅需提交字符串参数,无需上传文件:

val client = HttpClient(CIO)

val response: HttpResponse = client.post("http://localhost:8080/upload") {
    setBody(MultiPartFormDataContent(
        formData {
            append("description", "Ktor logo")
            append("image", File("ktor_logo.png").readBytes(), Headers.build {
                append(HttpHeaders.ContentType, "image/png")
                append(HttpHeaders.ContentDisposition, "filename=\"ktor_logo.png\"")
            })
        },
        boundary = "WebAppBoundary"
    )
    )
    onUpload { bytesSentTotal, contentLength ->
        println("Sent $bytesSentTotal bytes from $contentLength")
    }
}

尝试给prompt字段添加Content-Type头,问题依旧:

formData {
     append("prompt", text, Headers.build {
         append(HttpHeaders.ContentType, "text/plain")
     }) }

最终解决方案

给表单字段名称和Content-Disposition头中的name值都添加额外的引号后,请求正常返回结果,最终代码如下:

suspend fun generateImageOfText(text: String,aspectRatio: String = "1:1", apiKey: String): Result {
        return try {
            val response = httpClient.post("https://api.stability.ai/v2beta/stable-image/generate/core") {
                header(HttpHeaders.Authorization, "Bearer $apiKey")
                header(HttpHeaders.Accept, "application/json")
                setBody(MultiPartFormDataContent(
                    formData {
                        append("\"prompt\"", text, Headers.build {
                            append(HttpHeaders.ContentDisposition, "form-data; name=\"prompt\"")
                        })
                    }
                ))
            }
            val result: Base64Result = response.body()
            Result.Success(result)
        }catch (e: Exception){
            e.printStackTrace()
            (Result.Error(e.message ?: "Unknown error"))
        }
    }

内容的提问来源于stack exchange,提问作者trinadh thatakula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:27:10