13

How to add multiple images/files on a same parameter along with other textual data using retrofit?

Single image is uploading perfectly using following interface
    @Multipart
    @POST("/users/updateProfile/")
    public void updateProfileWithImage(
                    @Part("user_id") TypedString first_name,
                    @Part ("image") TypedFile image, 
                    Callback<WebResponse> callback);
mahsanq
  • 131
  • 1
  • 5

2 Answers2

12

You can use the @MultiPart Post with @PartMap as parameter

Map<String, TypedFile> files = new HashMap<String, TypedFile>();
files.put("my file number one", new TypedFile("image/jpg", new File(filename)));
files.put("my file number two", new TypedFile("image/jpg", new File(filename)));

apiInterface.updateProfileWithImage("first name here", files);

private interface ApiInterface{
    @Multipart
    @POST("/users/updateProfile/")
    Response updateProfileWithImage(
     @Part("user_id") TypedString first_name,
     @PartMap Map<String,TypedFile> Files
    );

}
Francois
  • 10,465
  • 4
  • 53
  • 64
  • 1
    In twitter, we need to specify the same file name for that, `files.put("media[]", file); files.put("media[]", file);` So, here comes the problem of not uploading multiple files. @Francois Any solution to this ? – Yash Sodha Apr 28 '15 at 14:03
  • 1
    @YashSodha did you find a solution? – Boris Treukhov Aug 28 '15 at 14:58
  • @BorisTreukhov nope, instead I had to set off with multiple tweets with different pic – Yash Sodha Aug 28 '15 at 15:00
  • 1
    @YashSodha actually MultipartTypedOutput solved the problem, thanks. The only thing I missed was the square brackets. – Boris Treukhov Aug 28 '15 at 15:57
  • one question @francois what if i wanna send multiple files with same name then how to do that as in map it has unique key therefore if i will add suppose 5 files with same name it will contain only one file with that name rest will be deleted from the map?? – aman verma Oct 24 '15 at 06:52
12

Retrofit 2.0 + OkHttp 3

Interface declaration:

@POST("postpath")
Call<Void> upload(@Body MultipartBody filePart);

Creating MultiPartBody:

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

then for each file(you can also add custom fields)

requestBodyBuilder.addFormDataPart("extraImage[]", "photo.jpg",
                            RequestBody.create(MediaType.parse("image/jpeg"), byteArrayOrFile));

and finally

api.upload(requestBodyBuilder.build());

P.S. you can add custom form fields (for example client.name) to the same form with

requestBodyBuilder.addFormDataPart("client[name]", null, RequestBody.create(MediaType.parse("text/plain"), name))

or

requestBodyBuilder.addFormDataPart("client[name]", name)) 

Retrofit 1.9:

You can use MultipartTypedOutput to post variable number of multi-part parameters.

In addition to François' answer, to post multiple images with the same / repeating field name(as an array) in retrofit you can use MultipartTypedOutput

Method signature:

@POST("/postpath")
SomeResponse upload(@Body MultipartTypedOutput output);

Usage:

MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
multipartTypedOutput.addPart("mainImage", new TypedFile("image/jpeg", mainImage));
multipartTypedOutput.addPart("extraImage[]", new TypedFile("image/jpeg", file1));
multipartTypedOutput.addPart("extraImage[]", new TypedFile("image/jpeg", file2));
upload(multipartTypedOutput);

Square brackets

Please note that some server side frameworks(Rails) typically require square brackets(i.e. extraImage[] instead of extraImage), others don't (Spring MVC).

Boris Treukhov
  • 17,493
  • 9
  • 70
  • 91