Search code examples
androidretrofit2image-uploadingmultipart

Retrofit 2 Multipart image upload with data


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


Solution

  • 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