如何在翻新中使用@Part传递标题?

时间:2018-08-07 16:21:58

标签: android header retrofit retrofit2 multipart

我的界面就是这样

    @Multipart
    @NonNull
    @FormUrlEncoded
    @POST("upload")
    Call<GeneralResponse> uploadImage(@Header("Authorization") MultipartBody.Part token, @Part("image") MultipartBody.Part image, @Part("kilometer") MultipartBody.Part distance);

上传图像和数据的方法

public void upload(final String token,final String distance, final File image) {

    InternetConnection internetConnection = new InternetConnection(TimeCard.this);
    if (internetConnection.isConnectingToInternet()) {
        showProgressDialog();
        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

        MultipartBody.Part bodykm;
        RequestBody kilometer;
        kilometer= RequestBody.create(MediaType.parse("text/plain"), distance);
        bodykm =MultipartBody.Part.createFormData("kilometer", distance, kilometer);


       Call<GeneralResponse> call = apiService.uploadImage(token,bodyImage,bodykm);
        call.enqueue(new Callback<GeneralResponse>() {
            @Override
            public void onResponse(Call<GeneralResponse> call, final Response<GeneralResponse> response) {

                try {
                    if(response.body().getStatus()){

                        meterImage = "";
                        distanceKm = "";
                        Toast.makeText(TimeCard.this,response.body().getMessage(),Toast.LENGTH_LONG).show();
                    }else {
                        Toast.makeText(TimeCard.this,response.body().getMessage(),Toast.LENGTH_LONG).show();
                    }
                }catch (Exception e){
                    progressDialog.dismiss();
                    e.printStackTrace();
                    Toast.makeText(TimeCard.this,e.getMessage(),Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<GeneralResponse> call, Throwable t) {
                progressDialog.dismiss();
                Toast.makeText(TimeCard.this,"Server error please try again later",Toast.LENGTH_LONG).show();
            }
        });
    } else {
        Toast.makeText(TimeCard.this,"Please check your internet connection",Toast.LENGTH_LONG).show();
    }
}

它给出了错误,因为只允许一种类型的注释。所以我将@Header更改为@Part

@Multipart
    @NonNull
    @FormUrlEncoded
    @POST("upload")
    Call<GeneralResponse> uploadImage(@Part("Authorization") MultipartBody.Part token, @Part("image") MultipartBody.Part image, @Part("kilometer") MultipartBody.Part distance);

现在如何传递标头? (如何将标头转换为MultipartBody.Part?)

1 个答案:

答案 0 :(得分:4)

我将从回答您的问题开始

  

由于只允许一种类型的注释,因此会出错

是的,这是改造的预期行为。您不能一次使用多个注释。因此,只需从@FormUrlEncoded方法中删除uploadImage()注释。

现在,您要发布距离以及图像。为此,您应该在uploadImage()方法(在服务类中)内部使用以下代码。

@Part("kilometer") RequestBody distance   // note: use RequestBody instead of MultipartBody.Part

upload()函数(在“活动”中)中进行更改。

RequestBody kilometer = RequestBody.create(MediaType.parse("text/plain"), distance);

现在开始提问

  

如何在改造中使用@Part传递标头?

我假设您具有动态授权密钥(通过查看有问题的示例代码)。

如果在运行时将动态授权密钥设置为标头,则可以使用Retrofit的@HeaderMap批注。

只需在uploadImage()方法中进行以下更改。

@HeaderMap Map<String, String> token

内部活动准备标题映射如下。

Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token);

如果要设置其他标头参数,请在同一标头哈希图中进行设置。

然后将此标头映射传递到您的uploadImage()方法。

因此,代码中的最终更改是这样的。

您的服务界面

@Multipart
@NonNull
@POST("upload")
Call<GeneralResponse> uploadImage(@HeaderMap Map<String, String> token, @Part("image") MultipartBody.Part image, @Part("kilometer") RequestBody distance);

和活动

public void upload(final String token,final String distance, final File image) {

InternetConnection internetConnection = new InternetConnection(TimeCard.this);
if (internetConnection.isConnectingToInternet()) {
    showProgressDialog();
    ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

    // prepare distance body
    RequestBody kilometer = RequestBody.create(MediaType.parse("text/plain"), distance);

    // prepare headers
    Map<String, String> headers = new HashMap<>();
    headers.put("Authorization", token);

   Call<GeneralResponse> call = apiService.uploadImage(headers, bodyImage, kilometer);
    call.enqueue(new Callback<GeneralResponse>() {
        @Override
        public void onResponse(Call<GeneralResponse> call, final Response<GeneralResponse> response) {

            try {
                if(response.body().getStatus()){

                    meterImage = "";
                    distanceKm = "";
                    Toast.makeText(TimeCard.this,response.body().getMessage(),Toast.LENGTH_LONG).show();
                }else {
                    Toast.makeText(TimeCard.this,response.body().getMessage(),Toast.LENGTH_LONG).show();
                }
            }catch (Exception e){
                progressDialog.dismiss();
                e.printStackTrace();
                Toast.makeText(TimeCard.this,e.getMessage(),Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<GeneralResponse> call, Throwable t) {
            progressDialog.dismiss();
            Toast.makeText(TimeCard.this,"Server error please try again later",Toast.LENGTH_LONG).show();
        }
    });
} else {
    Toast.makeText(TimeCard.this,"Please check your internet connection",Toast.LENGTH_LONG).show();
}
}

额外

如果您具有静态令牌(每个用户或API密钥永不更改的令牌),则无需在此处使用标头映射模式。只需跳过@HeaderMap注释/参数。进行如下更改。

@Headers("Authorization: your_token_key_here")
@Multipart
@NonNull
@POST("upload")
Call<GeneralResponse> uploadImage(@Part("image") MultipartBody.Part image, @Part("kilometer") RequestBody distance);

同样,如果您有多个标头,请将标头参数放在{}大括号内。

@Headers({
           "Authorization: your_token_key_here",
           "Content-Type: application/json", //  just an example
           "some other header here"
         })
@Multipart
@NonNull
@POST("upload")
Call<GeneralResponse> uploadImage(@Part("image") MultipartBody.Part image, @Part("kilometer") RequestBody distance);