仅使用表单数据

时间:2016-06-14 14:26:48

标签: android retrofit2 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);

我只是将身体变为 null 。它正在与POSTMAN合作。

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

我正在尝试查找改造不支持表单数据吗?

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生成代码

7 个答案:

答案 0 :(得分:28)

在改造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);

答案 1 :(得分:14)

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

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);

希望它有所帮助。

答案 2 :(得分:1)

对于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>

答案 3 :(得分:1)

<块引用>

这是在 Kotlin 中使用请求正文表单数据的另一个解决方案。这个解决方案在 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>) { }
})
<块引用>

您应该像这样为您的参数使用 RequestBody 类型。

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

答案 4 :(得分:0)

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

我在这里尝试了Retrofit - Send request body as array or numberHow to send PUT request with retrofit string and array list of model I need to use URL encoded的几种变体,但是它们没有用。然后我尝试了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中的外观。

答案 5 :(得分:0)

肯定支持

表单数据。 我将通过一个典型的注册过程示例来使您清楚。 首先添加标题

@FormUrlEncoded

在您的 用户客户端 中。 使用

@FieldMap

代替直接对象。因此,您的 user-client 代码将是这样的

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

现在在您的主要活动中,像这样为您的所有数据创建一个哈希表,

 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);

现在简单地将此哈希图传递给这样的方法

 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();
        }
    });

答案 6 :(得分:-1)

我认为这可以帮助您

  @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>