Retrofit 2 Multipart image upload with data

28,183

Solution 1

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

enter image description here

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

Solution 2

get Image like this

Uri mImageUri = data.getData();

// Get the cursor
Cursor cursor = getContentResolver().query(mImageUri, 
    filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageURI = cursor.getString(columnIndex);
cursor.close(); 

File file = new File(mImageUri.getPath())
RequestBody reqFile = RequestBody.create(okhttp3.MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image",
    file.getName(), reqFile);

Solution 3

This is my activity code where i am using multipart to show images, follow this code:

public void uploadimage()
{
    String filePath = getRealPathFromURIPath(uri1, DriverDetails.this);
    Log.d("hanish123456","File path->  "+filePath);
    file1 = new File(filePath);
    Log.d("uploadimage", "Filename " + profileimage1);
    Bitmap bmp = BitmapFactory.decodeFile(file1.getAbsolutePath());
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 30, bos);

    MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("image", profileimage1,
            RequestBody.create(MediaType.parse("image/*"), bos.toByteArray()));
    RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), profileimage1);

    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(3, TimeUnit.MINUTES)
            .readTimeout(3,TimeUnit.MINUTES)
            .writeTimeout(3,TimeUnit.MINUTES).build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(SERVER_PATH)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    ApiService uploadImage = retrofit.create(ApiService.class);

    Log.d("uploadimage", fileToUpload+"   "+filename);
    Call<ProfileResponse> fileUpload = uploadImage.uploadFile(fileToUpload, filename);
    fileUpload.enqueue(new Callback<ProfileResponse>() {
        @Override
        public void onResponse(Call<ProfileResponse> call, Response<ProfileResponse> response) {
            if(response.isSuccessful()){
                Toast.makeText(DriverDetails.this,"Successful  "+ response.raw().message(), Toast.LENGTH_LONG).show();
            }
            else {
                Toast.makeText(DriverDetails.this, response.raw().message(), Toast.LENGTH_LONG).show();
            }
            // Toast.makeText(MainActivity.this, "Success " + response.body().getSuccess(), Toast.LENGTH_LONG).show();
            Log.d("uploadimage", "No Error ");
        }
        @Override
        public void onFailure(Call<ProfileResponse> call, Throwable t) {
            if (t instanceof SocketTimeoutException) {
                Log.d("uploadimage", "Error occur " + t.getMessage());
            }
        }
    });
}
Share:
28,183
Wasi Sadman
Author by

Wasi Sadman

Updated on November 23, 2020

Comments

  • Wasi Sadman
    Wasi Sadman over 3 years

    Hello everyone I want to post image and other data through Retrofit2. I am sending data with one image.

    All the other info is storing but my image is not storing.while i am testing with postman, it works.

    enter image description here

    please guide me where I am lacking in my code

    This is the postman code snippet that works

    OkHttpClient client = new OkHttpClient();
    
    MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
    RequestBody body = RequestBody.create(mediaType, "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"email\"\r\n\r\[email protected]\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n123456\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nTest\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"phone\"\r\n\r\n1234567890\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image\"; filename=\"03.JPG\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
    Request request = new Request.Builder()
      .url("https://"url"/api/v1/sign-up")
      .post(body)
      .addHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
      .addHeader("cache-control", "no-cache")
      .addHeader("postman-token", "2dd038d9-5f52-fcd0-9331-445eaf35c230")
      .build();
    
    Response response = client.newCall(request).execute();
    

    Below is the postman request image:

    enter image description here

    this is my Retrofit api

        @Multipart
        @POST("sign-up")
        Call<SignUpResponse> getSignUpResponse(
                @Part("email") RequestBody email,
                @Part("password") RequestBody password,
                @Part("name") RequestBody name,
                @Part("phone") RequestBody phone,
                @Part MultipartBody.Part image
                //@Part("image") RequestBody image // i have thried them both but they didnt work
                //@Part("image\"; filename=\"pp.jpg\" ") RequestBody image
        );
    

    this is my client area:

    private RetrofitClient() {
    
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(logging);  // <-- this is the important line!
    
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();
    }
    

    and this is the part where i am making the request:

    RequestBody namePart = RequestBody.create(MultipartBody.FORM, "nameasd");
    RequestBody emailPart = RequestBody.create(MultipartBody.FORM, "[email protected]");
    RequestBody mobilePart = RequestBody.create(MultipartBody.FORM, "123456623");
    RequestBody passwordPart = RequestBody.create(MultipartBody.FORM, "123456123");
    //String filepath = "/storage/0403-0201/DCIM/Camera/20180926_203219.jpg"; this is the image source
    File file = new File(filepath);
    RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
    //RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
    MultipartBody.Part body = MultipartBody.Part.createFormData("image",file.getName(),reqFile);
    
    Call<SignUpResponse> call = RetrofitClient.getInstance().getApi().getSignUpResponse(emailPart, passwordPart, namePart, mobilePart, body);
                    call.enqueue(new Callback<SignUpResponse>() {
                        @Override
                        public void onResponse(Call<SignUpResponse> call, Response<SignUpResponse> response) {
                            progressDialog.dismiss();
                            Log.d(TAG, "onResponse: "+response.body());
                            Log.d(TAG, "onResponse: meta: " + response.body().getMeta().getStatus());
                        }
                        @Override
                        public void onFailure(Call<SignUpResponse> call, Throwable t) {
                            Toast.makeText(SignupActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                            Log.d(TAG, "onFailure: "+t.getMessage());
                        }
                    });
    

    this is the code where i get the data

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // get selected images from selector
            if (requestCode == REQUEST_CODE) {
                if (resultCode == RESULT_OK) {
    
                    mResults = data.getStringArrayListExtra(SelectorSettings.SELECTOR_RESULTS);
                    imagePath = mResults.get(0);
                    Glide.with(SignupActivity.this)
                            .load(mResults.get(0))
                            .into(profileImage);
                  }
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
    

    I even set it on a view and that works...

  • Wasi Sadman
    Wasi Sadman over 5 years
    i think here "companyLogo" should be "image" in my case?
  • Wasi Sadman
    Wasi Sadman over 5 years
    i have already tried "multipart/form-data"... it is not working for me...
  • s.j
    s.j over 5 years
    to check in postman simply add your base url following with Api service post request. in postman body add key values to get data in this format { "id":"1", "user_type":"1" }
  • Wasi Sadman
    Wasi Sadman over 5 years
    Log.d("uploadimage", "Filename " + profileimage1); what is your profileimage1? is it a path or file?
  • Bhuvaneshwaran Vellingiri
    Bhuvaneshwaran Vellingiri over 5 years
    RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); this should work
  • Wasi Sadman
    Wasi Sadman over 5 years
    String filepath = "/storage/0403-0201/DCIM/Camera/20180926_203219.jpg"; i have hard-coded the file path. it it wrong?
  • Wasi Sadman
    Wasi Sadman over 5 years
    RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); i have already tried it. it is not wotking @BhuvaneshwaranVellingiri
  • s.j
    s.j over 5 years
    its variable defined in activity to get image.
  • Wasi Sadman
    Wasi Sadman over 5 years
    sthill facing the sam problem... image is not storing
  • Archu Mohan
    Archu Mohan over 5 years
    use okhttp3 in mediatype
  • Ibrahim Sušić
    Ibrahim Sušić about 5 years
    @Body parameters cannot be used with form or multi-part encoding.
  • Wasi Sadman
    Wasi Sadman about 5 years
    Can you please explain why it cannot be used with form or multi-part encoding? @IbrahimSušić
  • Ibrahim Sušić
    Ibrahim Sušić about 5 years
    Sorry my wrong , I was implemented in network @Multipart . That made me a problem. Thank you for answer :)
  • sanjana
    sanjana over 3 years
    How to send arraylist containing image nd string in obj ??
  • Rahul Pandey
    Rahul Pandey almost 2 years
    @sanjana did you get the answer ? and what library did you use?, Retrofit or volley