Post Multipart Form Data Using Retrofit 2.0 Including Image

POST Multipart Form Data using Retrofit 2.0 including image

I am highlighting the solution in both 1.9 and 2.0 since it is useful for some

In 1.9, I think the better solution is to save the file to disk and use it as Typed file like:

RetroFit 1.9

(I don't know about your server-side implementation) have an API interface method similar to this

@POST("/en/Api/Results/UploadFile")
void UploadFile(@Part("file") TypedFile file,
@Part("folder") String folder,
Callback<Response> callback);

And use it like

TypedFile file = new TypedFile("multipart/form-data",
new File(path));

For RetroFit 2 Use the following method

RetroFit 2.0 ( This was a workaround for an issue in RetroFit 2 which is fixed now, for the correct method refer jimmy0251's answer)

API Interface:

public interface ApiInterface {

@Multipart
@POST("/api/Accounts/editaccount")
Call<User> editUser(@Header("Authorization") String authorization,
@Part("file\"; filename=\"pp.png\" ") RequestBody file,
@Part("FirstName") RequestBody fname,
@Part("Id") RequestBody id);
}

Use it like:

File file = new File(imageUri.getPath());

RequestBody fbody = RequestBody.create(MediaType.parse("image/*"),
file);

RequestBody name = RequestBody.create(MediaType.parse("text/plain"),
firstNameField.getText()
.toString());

RequestBody id = RequestBody.create(MediaType.parse("text/plain"),
AZUtils.getUserId(this));

Call<User> call = client.editUser(AZUtils.getToken(this),
fbody,
name,
id);

call.enqueue(new Callback<User>() {

@Override
public void onResponse(retrofit.Response<User> response,
Retrofit retrofit) {

AZUtils.printObject(response.body());
}

@Override
public void onFailure(Throwable t) {

t.printStackTrace();
}
});

Retrofit 2 Multipart image upload with data

We test api in Postman... So my Create Post Answer includes (all Dynamic)

  • Headers
  • Simple Strings
  • Single Image
  • Array Of Images
  • Array Of Categories
  • Array Of Features

Almost all things

Below is the Postman image for api testing...
You will get clear concept of request

  • Headers Image

Sample Image

So for this ...
Below is my Api...

@POST("post-create")
Call<PostCreateResponse> getPostCreateBodyResponse(
@Header("Accept") String accept,
@Header("Authorization") String authorization,
@Body RequestBody file
);

Now Retrofit Client area--->

private Retrofit retrofit;

// This is Client
private RetrofitClient() {

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

httpClient.connectTimeout(100, TimeUnit.SECONDS);
httpClient.readTimeout(100,TimeUnit.SECONDS);
httpClient.writeTimeout(100,TimeUnit.SECONDS);
httpClient.addInterceptor(logging); // <-- this is the important line!

retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}

This is the way I Made the Request...

/*
* -------------- Retrofit post Create single featured Image Working with MultipartBody -----------
* */

progressDialog.show();

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

builder.addFormDataPart("title", "3 room Current Free")
.addFormDataPart("location", "Dhaka")
.addFormDataPart("latitude", "23.7515")
.addFormDataPart("longitude", "90.3625")
.addFormDataPart("condition", "1")
.addFormDataPart("rent_amount", "123456")
.addFormDataPart("is_negotiable", "0")
.addFormDataPart("available_from", "2018-10-15");

// Categories
for (int categoryId : categories) {
builder.addFormDataPart("categories[]", String.valueOf(categoryId));
}
// Features
for (Integer featureId : features) {
builder.addFormDataPart("features[]", String.valueOf(featureId));
}

// featured Image
if (photoPaths.get(0) != null) {
File featured_image = new File(photoPaths.get(0));
if (featured_image.exists()) {

// If you want to use Bitmap then use this

Bitmap bmp = BitmapFactory.decodeFile(featured_image.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 30, bos);

builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, bos.toByteArray()));


// If you want to use direct file then use this ( comment out the below part and comment the above part )

//builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, featured_image));
}
}

// Images
for (String photoPath : photoPaths) {
if (photoPath != null) {
File images = new File(photoPath);
if (images.exists()) {
builder.addFormDataPart("images[]", images.getName(), RequestBody.create(MultipartBody.FORM, images));
}
}
}

RequestBody requestBody = builder.build();
Call<PostCreateResponse> call = RetrofitClient.getInstance().getApi().getPostCreateBodyResponse(Accept, Authorization, requestBody);
call.enqueue(new Callback<PostCreateResponse>() {
@Override
public void onResponse(Call<PostCreateResponse> call, Response<PostCreateResponse> response) {
progressDialog.dismiss();
Log.d(TAG, "onResponse: response code: retrofit: " + response.code());
}

@Override
public void onFailure(Call<PostCreateResponse> call, Throwable t) {

}
});

/*
* ---------------- Retrofit post Create single featured Image Working with MultipartBody----------------
* */

I hope this will help you all... thanks

Sending string and images with retrofit multipart/form-data

Step-1 : Create on interface method for call retrofit api

 @POST(Const.Task_Ans_FILE_NAME)
Call<TaskInfoBean> verifyTaskAns(@Body RequestBody file);

Step-2: Use below code to send multipart image data along with other field in body.

RetroFitService retroFitService = RetrofitClient.getAppData();
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if (answer_type.equals("1")) {
builder.addFormDataPart(Const.ANSWER, answer);
} else {
try {
builder.addFormDataPart(Const.ANSWER, Const.SelectedFileName, RequestBody.create(MultipartBody.FORM, Const.BOS.toByteArray()));
}catch (Exception e){
Log.e(TAG, "doInBackground: "+e.getMessage() );
}

}
builder.addFormDataPart(Const.LOGIN_ID, login_id)
.addFormDataPart(Const.USER_ID, user_id)
.addFormDataPart(Const.PLAY_ID, play_id)
.addFormDataPart(Const.TASK_ID, task_id)
.addFormDataPart(Const.SCENARIO, scenario)
.addFormDataPart(Const.ANSWER_TYPE,answer_type)
.addFormDataPart(Const.SKIP, skip);


final RequestBody requestBody = builder.build();

Call<TaskInfoBean> call = retroFitService.verifyTaskAns(requestBody);
call.enqueue(new Callback<TaskInfoBean>() {
@Override
public void onResponse(Call<TaskInfoBean> call, Response<TaskInfoBean> response) {
if(response.code()==200) {
TaskInfoBean taskInfoBean = response.body();
listener.OnVerifyTaskAns(taskInfoBean);
}else{
Log.e(TAG, "onResponse: "+response.toString() );
}
}

@Override
public void onFailure(Call<TaskInfoBean> call, Throwable t) {
Log.e(TAG, "onFailure: " + t.toString());
}
});
return null;
}

Step-3: Call this method in your activity/fragment.

Retrofit Post Multipart form data values are empty

I managed to solve the issue. It seems that the solution was as simple as removing the @Header annotation from the API interface method. So now it looks like this:

@Multipart
@POST("/companies/uploadImage")
Call<ServerResponse> companyUploadImage( @Part("company_id") RequestBody companyId, @Part MultipartBody.Part file, @Query("token") String token);

Maybe someone will find this post helpful.



Related Topics



Leave a reply



Submit