Retrofit 2 Multipart image upload with data
Asked Answered
G

5

18

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

Gallopade answered 28/9, 2018 at 10:19 Comment(5)
filepath inside have an image?Pragmatism
yes.. it has an image...Gallopade
check file is null or valuable? if (file!= null)Pragmatism
String path = Environment.DIRECTORY_DCIM + "/Camera/IMG_20180928_071551.jpg"; path use like this.Pragmatism
and change image to multipart RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); it should workPragmatism
G
32

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

Gallopade answered 3/10, 2018 at 6:26 Comment(3)
@Body parameters cannot be used with form or multi-part encoding.Styrax
Can you please explain why it cannot be used with form or multi-part encoding? @IbrahimSušićGallopade
Sorry my wrong , I was implemented in network @Multipart . That made me a problem. Thank you for answer :)Styrax
R
3

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);
Refugiorefulgence answered 28/9, 2018 at 10:30 Comment(7)
i think here "companyLogo" should be "image" in my case?Gallopade
i have already tried "multipart/form-data"... it is not working for me...Gallopade
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); this should workPragmatism
String filepath = "/storage/0403-0201/DCIM/Camera/20180926_203219.jpg"; i have hard-coded the file path. it it wrong?Gallopade
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); i have already tried it. it is not wotking @BhuvaneshwaranVellingiriGallopade
sthill facing the sam problem... image is not storingGallopade
use okhttp3 in mediatypeRefugiorefulgence
E
2

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());
            }
        }
    });
}
Emu answered 28/9, 2018 at 10:37 Comment(4)
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" }Emu
Log.d("uploadimage", "Filename " + profileimage1); what is your profileimage1? is it a path or file?Gallopade
its variable defined in activity to get image.Emu
where is uploadImage.uploadFile(fileToUpload, filename);Florina
B
1

there one more simple way to send other data, you can send Hashmap<String,String>

@Multipart
    @POST("sign-up")
    Call<SignUpResponse> getSignUpResponse(@Part MultipartBody.Part file, @PartMap() Map<String, String> partMap); 
Bonehead answered 28/9, 2018 at 11:40 Comment(2)
How to send arraylist containing image nd string in obj ??Aggrade
@Aggrade did you get the answer ? and what library did you use?, Retrofit or volleyOverweening
M
-1

MultipartBody.Part.createFormData("file","fileName",RequestBody.create(okhttp3.MediaType.parse("image/*"), file))

Marcel answered 13/2, 2023 at 6:56 Comment(1)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Elitism

© 2022 - 2024 — McMap. All rights reserved.