改造 2 只有 form-data

Retrofit 2 with only form-data

我正在尝试使用 Retrofit 2 发出 POST 请求。请求类型是 form-data NOT application/x-www-form-urlencoded.

我只发布数据而不是请求中的文件,响应采用 JSON.

的形式

我已经尝试 @FormUrlEncoded, @Multipart 但它不起作用。

我已经尝试按照要求

1.第一次尝试

@FormUrlEncoded
@POST("XXXX")
Call<PlanResponse> getPlanName(@Field(Constants.ACTION_ID) String actionId, @Field(Constants.OFFER_CODE) String offerCode);

2。第二次尝试

@Headers({"Content-Type: multipart/form-data","Content-Type: text/plain"})
@FormUrlEncoded
@POST("XXXX")
Call<PlanResponse> getPlans(@Body @FieldMap(encoded = false) Map<String, String> data);

3。第三次尝试

@Headers("Content-Type: multipart/form-data")
@Multipart
@POST("XXXX")
Call<PlanResponse> myPlans(@Part(Constants.ACTION_ID) String actionId, @Part(Constants.OFFER_CODE) String offerCode);

我只得到 body 作为 null。它正在与 POSTMAN 一起工作。

我还搜索了 form-dataapplication/x-www-form-urlencoded,发现如果数据是二进制的,则使用 form-data,如果数据是 ASCII,则使用 application/x-www-form-urlencoded

我正在尝试查找 Retrofit 是否不支持 form-data?

POSTMAN 请求

Cache-Control: no-cache
Postman-Token: XXXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXX
Content-Type: multipart/form-data; boundary=----    WebKitFormBoundaryXXXXXXXXXXXX


 ----WebKitFormBoundaryXXXXXXXXXXXX
Content-Disposition: form-data; name="actionId"

1000
 ----WebKitFormBoundaryXXXXXXXXXXXX
Content-Disposition: form-data; name="offerCode"

MYCODE
----WebKitFormBoundaryXXXXXXXXXXXX

我只能添加从 POSTMAN

截取的 HTTP 生成代码

在改造 2.0 中执行上述 POST 请求,您应该像这样为您的参数使用 RequestBody 类型。

@Multipart
@POST("XXXX")
Call<PlanResponse> myPlans(@Part(Constants.ACTION_ID) RequestBody actionId, @Part(Constants.OFFER_CODE) RequestBody offerCode);

以及如何从 String 获取 requestBody。

String somevalue = "somevalue";
RequestBody body = RequestBody.create(MediaType.parse("text/plain"), somevalue);

这是另一个使用请求正文的解决方案:

RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("param1", param1)
        .addFormDataPart("param2", param2)
        .build();

apiInterface.somePostMethod(requestBody).enqueue(
    //onResponse onFailure methods
);

这是我的 api 界面 POST 方法

@POST("somePostMethod")
Call<ResponseBody> somePostMethod(@Body RequestBody body);

希望对您有所帮助。

我想将一组 ID 传递给现有请求。

我从这里尝试了几种变体,Retrofit - Send request body as array or number, , but they didn't work. Then I tried android retrofit send array as x-www-form-urlencoded

我将 [] 添加到列表参数,并将 List 添加到它的类型:

@FormUrlEncoded
@POST("your_request/")
fun sendIds(
    @Field("token") token: String,
    @Field("city_id") cityId: Int?,
    @Field("description") description: String,
    @Field("ids[]") ids: List<Int>? // Add '[]' here.
): Deferred<YourResponse>

然后像往常一样调用它(使用 Kotlin 协程):

api.sendIds("f0123abc", null, "description", listOf(1, 2, 3)).await()

另请参阅 Is it possible to send an array with the Postman Chrome extension? 以了解它在 Postman 中的外观。

对于 Kotlin,这是另一种实现方式。对于不接受 FormUrEncoded 数据的 api。

 fun login(email: String, password: String, grantType: String):                             

  Single<TokenModel> {
     var userNameB:RequestBody= 
       email.toRequestBody(email.toMediaTypeOrNull())
     var passwordB: RequestBody =
       password.toRequestBody(password.toMediaTypeOrNull())
     var grantTypeB: RequestBody =
       grantType.toRequestBody(grantType.toMediaTypeOrNull())

  return userApi.loginUSer(userNameB,passwordB,grantTypeB)
   .map { TokenModel(it.accessToken, it.refreshToken) }

}

然后。

 @Multipart
 @POST("auth/token/")
 fun loginUSer(
    @Part("username") request: RequestBody,
    @Part("password") passwordB: RequestBody,
    @Part("grant_type") grantTypeB: RequestBody
 ): Single<Token>

form-data 是肯定支持的。 我将使用典型注册过程的示例让您清楚。 首先添加一个header

@FormUrlEncoded

在您的用户客户端。 使用

@FieldMap

而不是直接的对象。所以你的 user-client 代码会像这样

@POST("signup/")
@FormUrlEncoded
Call<ResponseModel> signup(@FieldMap Map<String,String> params);

现在在你的主 activity 中,像这样为你的所有数据创建一个 Hashmap,

 Map<String,String> params = new HashMap<String, String>();
    params.put("fullname", fullname);
    params.put("city", city);
    params.put("state",state);
    params.put("address",address);
    params.put("email",email);
    params.put("password1", password1);
    params.put("password2", password2);

现在简单地将这个 hashmap 传递到这样的方法中

 Call<ResponseModel> call = service.signup(params);
    call.enqueue(new Callback<ResponseModel>() {
        @Override
        public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) {
            if (response.isSuccessful()) {
                Toast.makeText(SignUp.this,response.body.getData,Toast.LENGTH_SHORT).show();
                
            } else {
                Toast.makeText(SignUp.this, "Error : ", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<ResponseModel> call, Throwable t) {
            t.printStackTrace();
            Toast.makeText(SignUp.this, "Server Unavailable : "+t.toString(), Toast.LENGTH_SHORT).show();
        }
    });

我想这对你有帮助

  @Multipart
@Headers( "Content-Type: application/x-www-form-urlencoded")
@POST("api/register")
fun postRegister(
    @Part("authtype") authtype: String,
    @Part("channel")channel : String,
    @Part("children")children : List<String>,
    @Part("names") names: List<String>,
    @Part("email") email: String,
    @Part("password")password : String,
    @Part("name") name: String,
    @Part("timezone") timezone: Int,
    @Part("timezone_name")timezone_name : String,
    @Part("token_device")token_device : String,
    @Part("imageData") imageData: String,
    @Part("mimeType") mimeType: String,
    @Part("extension") extension: String,
): Call<ResponseBase>

Here's another Solution using the request body form-data in Kotlin. This solution work for me in Kotlin.

val request = ServiceBuilder.buildService(TmdbEndpoints::class.java)
val requestBody: RequestBody = MultipartBody.Builder()
      .setType(MultipartBody.FORM)
      .addFormDataPart("email", "abc@gmail.com")
      .addFormDataPart("password", "admin")
      .addFormDataPart("push_token", "token")
      .addFormDataPart("device_id", "1112222")
      .addFormDataPart("platform", "android")
      .addFormDataPart("device_name", "my device")
      .addFormDataPart("version", "1.2")
      .build()
            
val call = request.userFigLogin(requestBody)

call.enqueue(object : Callback<LoginResult> {
     override fun onFailure(call: Call<LoginResult>, t: Throwable) { }

     override fun onResponse(call: Call<LoginResult>,
          response: retrofit2.Response<LoginResult>) { }
})

You should use RequestBody type for your parameter like this.

@POST("api/login")
fun userFigLogin(@Body body: RequestBody): Call<LoginResult>

只需将其从页眉中删除 defaultProperties["Content-Type"] = "application/json"