24

Is there any way to attached multiple images in one multipart request? The images is dynamic based on the number of images that user has picked.

Below code only works for single image:

Interface:

@Multipart
@POST("/post")
void createPostWithAttachments( @Part("f[]") TypedFile image,@PartMap Map<String, String> params,Callback<String> response);

Implementation:

TypedFile file = new TypedFile("image/jpg", new File(gallery.sdcardPath));

Map<String,String> params = new HashMap<String,String>();
params.put("key","value");

ServicesAdapter.getAuthorizeService().createPostWithAttachments(file,params, new Callback<String>() {
        @Override
        public void success(String s, Response response) {
            DBLogin.updateCookie(response);
            new_post_text.setText("");
            try {
                JSONObject json_response = new JSONObject(s);
                Toast.makeText(getApplicationContext(), json_response.getString("message"), Toast.LENGTH_LONG).show();
                if (json_response.getString("status").equals("success")) {
                    JSONObject dataObj = json_response.getJSONObject("data");
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Log.d(TAG, "Request failed");
                }
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
            }
        }

        @Override
        public void failure(RetrofitError retrofitError) {
            Toast.makeText(getApplicationContext(), retrofitError.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
Cœur
  • 37,241
  • 25
  • 195
  • 267
Louis Loo
  • 641
  • 1
  • 7
  • 11

2 Answers2

32

After look around with the documentation that provided by retrofit.. Im able to get it done by my own solution, maybe is not that good but still manage to get it works..

Here is the referece MultipartTypedOutput

Actually is quite similar to the previous code from above, just make a little bit changes

Interface

@POST("/post")
void createPostWithAttachments( @Body MultipartTypedOutput attachments,Callback<String> response);

Implementation

    MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
    multipartTypedOutput.addPart("c", new TypedString(text));
    multipartTypedOutput.addPart("_t", new TypedString("user"));
    multipartTypedOutput.addPart("_r", new TypedString(userData.user.id));

    //loop through object to get the path of the images that has picked by user
    for(int i=0;i<attachments.size();i++){
        CustomGallery gallery = attachments.get(i);
        multipartTypedOutput.addPart("f[]",new TypedFile("image/jpg",new File(gallery.sdcardPath)));
    }

    ServicesAdapter.getAuthorizeService().createPostWithAttachments(multipartTypedOutput, new Callback<String>() {
        @Override
        public void success(String s, Response response) {
            DBLogin.updateCookie(response);
            new_post_text.setText("");
            try {
                JSONObject json_response = new JSONObject(s);
                Toast.makeText(getApplicationContext(), json_response.getString("message"), Toast.LENGTH_LONG).show();
                if (json_response.getString("status").equals("success")) {
                    JSONObject dataObj = json_response.getJSONObject("data");
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Log.d(TAG, "Request failed");
                }
            } catch (Exception e) {
                Log.d(TAG, e.getMessage());
            }
        }

        @Override
        public void failure(RetrofitError retrofitError) {
            Toast.makeText(getApplicationContext(), retrofitError.getMessage(), Toast.LENGTH_LONG).show();
        }
    });

Maybe this solution is not that good but hopes it help someone else.

If there is any better solution please suggest, thank you :D

Updates

MultipartTypedOutput no longer exists in Retrofit 2.0.0-beta1

For those who want to upload multiple images now can use with @PartMap, reference link javadoc

Vincent D.
  • 977
  • 7
  • 20
Louis Loo
  • 641
  • 1
  • 7
  • 11
  • This worked great for me where I needed parts with the same name, but different values. Similar to an array, but the name could not have the "[]" with it and a new part. – Ray Hunter Jun 18 '15 at 05:14
  • 1
    works like a charm. thanks man!! Note: Don't forget to remove @Multipart annotation when using Body and POST! – voghDev Jul 16 '15 at 09:10
  • in my case MultipartTypedOutput is running slower than part i dont know why this is happening can you please tell me ?? – aman verma Oct 31 '15 at 20:30
  • Man please please tell me how you pick the images i dont umderstand the loop part, im about to lose my mind on this last feauter in my app – H4F Dec 27 '15 at 07:43
  • any solution for retrofit 2, since this does not work? – Jemshit Mar 21 '16 at 17:55
  • @JemshitIskenderov See a dupe question http://stackoverflow.com/questions/22658797/need-help-in-post-multiple-image-file-using-retrofit/32275127#32275127 – Boris Treukhov May 12 '16 at 17:27
4
//We need to create the Typed file array as follow and add the images path in the arrays list.



    private ArrayList<TypedFile> images;

        private void postService(final Context context) {
            Utils.progressDialog(context);
            MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
            multipartTypedOutput.addPart("user_id",new TypedString(strUserId));
            multipartTypedOutput.addPart("title", new TypedString(strJobtitle));
            multipartTypedOutput.addPart("description", new TypedString(
                    strJobdescription));
            multipartTypedOutput.addPart("experience", new TypedString(
                    strUserExperience));
            multipartTypedOutput.addPart("category_id", new TypedString(
                    strPostCategory));
            multipartTypedOutput.addPart("city_id", new TypedString(strCityCode));
            multipartTypedOutput.addPart("country_id", new TypedString(
                    strCountryCode));       
    multipartTypedOutput.addPart("profile_doc",new TypedFile("multipart/form-data", postCurriculamFile));
    for (int i = 0; i < images.size(); i++) {
                multipartTypedOutput.addPart("image[]", images.get(i));
    }       

    PostServiceClient.getInstance().postServiceData(multipartTypedOutput,
                    new Callback<RegistrationResponsModel>() {
                @Override
                public void failure(RetrofitError retrofitError) {
                    Logger.logMessage("fail" + retrofitError);
                    Utils.progressDialogdismiss(context);
                }

                @Override
                public void success(
                        RegistrationResponsModel regProfileResponse,
                        Response arg1) {
                    Utils.progressDialogdismiss(context);
                    UserResponse(regProfileResponse);
                }
            });
        }


    @POST("/service/update") // annotation used to post the data
    void postEditServiceData(@Body MultipartTypedOutput attachments, 
            Callback<RegistrationResponsModel> callback);

//This is the way we can post the file multipartTypedOutput.addPart("profile_doc",new TypedFile("multipart/form-data", postCurriculamFile));

//This is the way we can post the multiple images

    for (int i = 0; i < images.size(); i++) {
        multipartTypedOutput.addPart("image[]", images.get(i));
    }       
Dinesh IT
  • 87
  • 2
  • Seems interisting but what method is this postCurriculamFile? Im using usual gallery intent to select each image can you point me please – H4F Dec 26 '15 at 13:15
  • 1
    postCurriculamFile is the path of the document and the path file gets through Intent.if your posting images means no need of this line. if (fileType.equalsIgnoreCase("application/pdf") || fileType.equalsIgnoreCase("doc")) { Utils.savePreferences(context, "postservicefile", path); } – Dinesh IT Dec 28 '15 at 05:49
  • Thanks for replay actually I created a volley request for params and within it onresponse a retrofit request for images, it works fine but its a safe code? – H4F Dec 28 '15 at 06:43
  • Implementation its seems fine and its a safe code but the optimization perspective better go with retro fit.you can achieve both the image and param request. – Dinesh IT Dec 28 '15 at 10:00
  • Hard to understand it and im in harry it didnt work alone or i couldnt make it – H4F Dec 28 '15 at 11:58