Android中使用Retrofit上传多表单数据及图片返回status0问题求解
Retrofit上传文件接口返回成功但状态值为0的解决方法
问题背景
使用Retrofit上传文件和表单信息时,接口返回成功但状态值为0,Postman中用文件类型的photo参数能正常请求,推测是代码中文件传递方式有误。
问题原因分析
- 冗余的Content-Type头:接口中手动设置了
Content-Type: multipart/form-data,但Retrofit在处理@Multipart注解时会自动生成正确的请求头,手动添加反而可能导致请求格式异常。 - 文件MediaType不精确:使用
image/*作为文件的MediaType,部分服务端无法准确识别,可能导致文件解析失败。 - 参数写法不统一:部分参数用
toRequestBody,部分用RequestBody.create,虽然功能一致,但统一写法更易维护。
修正后的代码
1. MyAPI接口(移除冗余Header)
@Multipart @POST("edit_userinfo") @Headers( "Accept: */*" ) fun editProfile( @Part("languges") lang: RequestBody, @Part("user_id") userId: RequestBody, @Part("name") name: RequestBody, @Part("gender") gender: RequestBody, @Part("keyword") keyword: RequestBody, @Part("mobile") mobile: RequestBody, @Part image: MultipartBody.Part ): Call<UploadResponse> // Retrofit实例保持不变 return Retrofit.Builder() .baseUrl("http://phpstack-916737-3182297.cloudwaysapps.com/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(MyAPI::class.java)
2. MainActivity请求代码(优化MediaType和参数)
// 统一定义文本类型的MediaType val textType = "text/plain".toMediaTypeOrNull() // 统一使用toRequestBody创建文本参数 val lang = "English".toRequestBody(textType) val userId = "1".toRequestBody(textType) val name = "Test12".toRequestBody(textType) val gender = "male".toRequestBody(textType) val mobno = "1212121212".toRequestBody(textType) val keyword = "**********".toRequestBody(textType) // 根据文件实际类型设置精确的MediaType,比如image/jpeg、image/png val imageType = when (file.extension.lowercase()) { "png" -> "image/png".toMediaTypeOrNull() "jpg", "jpeg" -> "image/jpeg".toMediaTypeOrNull() else -> "image/*".toMediaTypeOrNull() } ?: "image/*".toMediaTypeOrNull() // 使用asRequestBody简化文件RequestBody创建 val imagePart = MultipartBody.Part.createFormData( "photo", file.name, file.asRequestBody(imageType) ) // 发起请求 val apiCall = MyAPI().editProfile(lang, userId, name, gender, keyword, mobno, imagePart) apiCall.enqueue(object : Callback<UploadResponse> { override fun onFailure(call: Call<UploadResponse>, t: Throwable) { Log.e("TAG", "onFailure: $t") t.printStackTrace() layout_root.snackbar(t.message!!) } override fun onResponse(call: Call<UploadResponse>, response: Response<UploadResponse>) { response.body()?.let { Log.e("TAG", "onResponse: success $it") layout_root.snackbar("Status -> $it") } } })
额外调试建议
- 添加OkHttp日志拦截器,打印完整的请求内容,对比Postman的请求格式,确认参数名、文件类型是否完全匹配。
- 检查服务端是否对文件大小、格式有校验限制,或者
photo参数名是否存在大小写错误。
内容的提问来源于stack exchange,提问作者mk_7
相关产品推荐
相关产品推荐

