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);
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
);
}
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).
Related
I am new to retrofit, i am trying to send arraylist<> of type string to server,
I have seen several solution on stack-overflow.
I am having problem on the method side. I don't know how can I send the array-list inside the method.
I have tried 2 different ways
Method1:
Here is my Interface:
#Multipart
#PUT("profile")
Call<ProfileSetupResponse3> vendorProfile3(
#Header("access-token") String token,
#Part("name") RequestBody name,
#Part("step") RequestBody step,
#Part("description") RequestBody description,
#Part("highlights") RequestBody highlights,
#Part("minQuantity") RequestBody minQuantity,
#Part("available") RequestBody available,
#Part("warrantyDetail") RequestBody warrantyDetail,
#Part("warrentyPeriod") RequestBody warrentyPeriod,
**#Query("categories[]") ArrayList<RequestBody> categories**
);
ArrayList<RequestBody> cat = new ArrayList<>();
cat.add(createFromString("Paintsas"));
Call<ProfileSetupResponse3> call = RetrofitClient
.getInstance()
.getApi()
.vendorProfile3(....,cat)
Method2:
#Query("categories[]") ArrayList<String> categories
ArrayList<String> categories = new ArrayList<>();
categories.add("APskaoj");
categories.add("APskaoj");
categories.add("APskaoj");
Call<ProfileSetupResponse3> call = RetrofitClient
.getInstance()
.getApi()
.vendorProfile3(....,categories)
Still I am not able to send my arraylist to server.
Some help will be really appreciated.
Apologies I cannot comment...
The Query parameter is appended to the URL for example:
#GET("/friends")
Call<ResponseBody> friends(#Query("page") int page);
Calling with foo.friends(1) yields /friends?page=1.
This is from the documentation of Retrofit2: https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/Query.html
Without seeing the API specification. I would say change the #Query to be #Body
I know it is not wise to use multipart for simple text authentication. but I need to use it with api provided to me.
I tried all the methods possible.
It's working fine with postman
but not with retrofit 2
request type details
request type details
code used
tried
//RequestBody requestNameRq = RequestBody.create(MediaType.parse("text/plain"),serviceNameValue);
//RequestBody requestAmountRq = RequestBody.create(MediaType.parse("text/plain"),serviceAmountValue.toString());
/* Create Request Body */
//MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM)
// .addFormDataPart("service",serviceNameValue)
// .addFormDataPart("amount", String.valueOf(serviceAmountValue));
//RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
// .addFormDataPart("service",serviceNameValue)
// .addFormDataPart("amount",serviceAmountValue.toString()).build();
//MultipartBody.Part multipartRequestBody = MultipartBody.Part
// .createFormData("service",serviceNameValue)
// .createFormData("amount",serviceAmountValue.toString());
//MultipartBody multipartBody = builder.build();
Code for Apiservice
#POST("services")
Call<AddServiceResponse> addService(#Header("Authorization") String authToken,
//#Body MultipartBody body);
#Part("service") RequestBody service,
#Part("amount") RequestBody amount);
//#Part("service") String service,
//#Part("amount") String password);
//#Part("service") RequestBody service,
//#Part("amount") RequestBody amount);
}
Please try to add
#Multipart
before
#POST("services")
Modify your ApiService class
#Multipart
#POST("services")
Call<AddServiceResponse> addService(
#Header("Authorization") String authToken,
#Part("service") MultipartBody.Part service,
#Part("amount") MultipartBody.Part amount);
Then create MultipartBody
MultipartBody.Part serviceBody = MultipartBody.Part.createFormData("service", "Somethin2");
MultipartBody.Part amountBody = MultipartBody.Part.createFormData("amount", "2344");
Then call
apiService.addService(serviceBody, amountBody);
I'm sending a multipart request to server and this is my interface:
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members") List<RequestBody> members);
and for sending my members in my fragment, I change my List<String> to List<RequestBody> as below:
List<RequestBody> members = new ArrayList<>();
for(int i = 0;i < membersId.size(); i++){
members.add(RequestBody.create(MediaType.parse("text/plain"),membersId.get(i)));
}
and it's working with multiple members! but when there is a one string in my list, retrofit doesn't sends my members as a list!!! for example:
I want to send array of strings like this :
["item1","item2","item3"]
my code works for this, but when there is only one item, retrofit sends this :
"item1"
instead of ["item1"]
what is the proper way of sending array of string in multipart with retrofit?
what am I doing wrong?
Use something like this.
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members[]") List<RequestBody> members);
Remember you must add [] to your members param :).
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members[]") ArrayList<RequestBody> members);
Two changes:
Change list to ArrayList as ArrayList is Serializable whereas List is not.
add "[]" at the end of the ArrayList type parameter.
I am using retrofit to upload image (base64 String) with data to server. Now i can send video or image depending on condition so i wanted to know how is it possible to upload it since video is much heavier. How do i upload video on retrofit with my other data. My previous method to send data with image was:
Map<String, Object> params = new HashMap<>();
params.put(URLParam.USER_ID, user.getId());
params.put(URLParam.MEDIA, mBase64String);
#Headers({"Accept: application/json", "Content-Type:application/json"})
#POST("/v1/address")
Call<ResponseBody> uploadPost(#Body Map<String, Object> params);
How do i send video now
Retrofit interface method would look like this..
#Multipart
#POST("/your url/")
Call<ResultObject> uploadVidToServer(#Part MultipartBody.Part video);
Send the file in multipart so that you can handle the progress dialog ...for better UI
Then make the retrofit call like this :-
File videoFile = new File(pathToVideoFile);
RequestBody videoBody = RequestBody.create(MediaType.parse("video/*"), videoFile);
MultipartBody.Part vFile = MultipartBody.Part.createFormData("video", videoFile.getName(), videoBody);
pathToVideoFile is the string path of your file
Finally make the call
Call<ResultObject> uploadVideo = vInterface.uploadVidToServer(vFile);
uploadVideo .enqueue........
Remember :-
Create the requestBody from your VideoFile that you want to upload.
Create MutlipartBody.Part object from the RequestBody object.
Then make the call.
I am writing a client-server Android application. I need to send a file created by user (photo) to server via POST request. The problem is, that when i try to send a file, i can't add a POST Field to my request. Maybe I'm wrong fundamentally, and this operation should be done another way?
#FormUrlEncoded
#Multipart
#POST("/answer/add-file")
Call<AbstractServerResponse> sendSingleFile(#Query("access-token") String accessToken,
#Query("w") String screenWidth,
#Field("answer_id") Integer answerId,
#Part("file") File fileToUpload);
When i try to send files in a multipart way only, i get an exception:
java.lang.IllegalStateException: JSON must start with an array or an object.
As I understand, this happends because the body (main part) of the request is empty.
Multipart requests are used when #Multipart is present on the method. Parts are declared using the #Part annotation.
------ from http://square.github.io/retrofit/
I'm using #Multipart in my project like this:
#POST("/{action}")//POST 多个文件
#Multipart
public void PostAPI(
#Path(value = "action", encode = false) String action,
#Part("path") TypedFile[] typedFiles,
#PartMap Map<String, String> params,
Callback<APIResponse> callback);
Maybe u can try this:
#Multipart
#POST("/answer/add-file")
Call<AbstractServerResponse> sendSingleFile(
#Query("access-token") String accessToken,
#Query("w") String screenWidth,
#Part("answer_id") Integer answerId,
#Part("file") File fileToUpload);
You cannot use both #FormUrlEncoded and #Multipart on a single method. An HTTP request can only have one Content-Type and both of those are content types.