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
相关产品推荐
相关产品推荐

