upload array of images in multipart retrofit2 - android

I need to upload an array of images on server using multi-part.and I Also want to give key to that array, otherwise server don't recognize the array. I have tried the solutions below, but these do not work:
Solution1 :
MultipartBody.Part[] array = new MultipartBody.Part[items.size()];
for(int i=0;i<items.size();i++){
File file = new File(items.get(i));
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("value_"
+ String.valueOf(uploadMissionRequestModel.getStepId()), file.getName(),
requestBody);
array[i]=filePart;
}
RequestBody apiKey = RequestBody.create(MediaType.parse("text/plain"),
uploadMissionRequestModel.getApiKey());
RequestBody stepId = RequestBody.create(MediaType.parse("text/plain"),
String.valueOf(uploadMissionRequestModel.getStepId()));
RequestBody missionId = RequestBody.create(MediaType.parse("text/plain"),
String.valueOf(uploadMissionRequestModel.getMissionId()));
RequestBody overWrite = RequestBody.create(MediaType.parse("text/plain"),
"yes");
Map<String, RequestBody> partMap = new HashMap<>();
partMap.put("api_token", apiKey);
partMap.put("MissionID", missionId);
partMap.put("overwrite", overWrite);
partMap.put("StepID", stepId);
ApiServices service = RestClient.getClient();
final Call<UploadMissionResponse> call = service.uploadFiles(partMap, array);
Solution2
RequestBody[] image_id = new RequestBody[items.size()];
for(int i=0;i<items.size();i++){
File file = new File(items.get(i));
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
image_id[i]=requestBody;
}
RequestBody apiKey = RequestBody.create(MediaType.parse("text/plain"),
uploadMissionRequestModel.getApiKey());
RequestBody stepId = RequestBody.create(MediaType.parse("text/plain"),
String.valueOf(uploadMissionRequestModel.getStepId()));
RequestBody missionId = RequestBody.create(MediaType.parse("text/plain"),
String.valueOf(uploadMissionRequestModel.getMissionId()));
RequestBody overWrite = RequestBody.create(MediaType.parse("text/plain"),
"yes");
Map<String, RequestBody> partMap = new HashMap<>();
partMap.put("api_token", apiKey);
partMap.put("MissionID", missionId);
partMap.put("overwrite", overWrite);
partMap.put("StepID", stepId);
Map<String, RequestBody[]> imageMap = new HashMap<>();
imageMap.put("value_8",image_id);
ApiServices service = RestClient.getClient();
final Call<UploadMissionResponse> call = service.uploadFiles(partMap, imageMap);
Please suggest, How I can pass array of images with key name using retrofit2.

My request method:
#Multipart
#POST("admin/assets/upload/")
Observable<UploadResponse> uploadFiles(#Part MultipartBody.Part... files);
Creating parts from array of uri's. All parts will have key 'files[]', the one my backend recognizes:
//UriHandle and OkioUtil are my own classes to handle both 'content' and 'file' uris
//files has type of Uri[]
final MultipartBody.Part[] parts = new MultipartBody.Part[files.length];
for (int i = 0; i < files.length; i++) {
final UriHandle handle = UriUtil.getUriHandle(context, files[i]);
final RequestBody body = OkioUtil.create(handle, mediaType);
parts[i] = MultipartBody.Part.createFormData("files[]", handle.name(), body);
}
Sending request:
api.uploadFiles(part)
.subscribeOn(...)
.observeOn(...)
.subscribe(result -> ...);

if I were you I would convert images to Base64 and send List<String> for images using your second solution.

Related

How can I add additional information with each multipart image file in okhttp3

Here, I am sending my image files to the server as multipart data dynamically:
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", json);
for (int i = 0; i < imageList.size(); i++) {
File imageFile = imageList.get(i).getImageFile();
if (imageFile.exists()) {
builder.addFormDataPart("images[" + i + "]", imageList.getName(), RequestBody.create(MediaType.parse("image"), imageFile));
}
}
MultipartBody requestBody = builder.build();
Now, I want to add an additional information created_at as String to each of the images to the server. How can I achieve this? Is it possible in Retrofit/Volley? Please help.
You can achive to your goal with code below
Your retrofit service
#Multipart
#POST(value = "example/endpoint")
Call<ResponseBody> uploadImages(
#Part(value = "created_at") RequestBody createdAt,
#Part(value = "image") MultipartBody.Part image
);
How to convert String to RequestBody
RequestBody.create(String.valueOf(createdAt), MediaType.parse("text/plain"));

How to Post image and data in android retrofit

I am unable to post data and image using retrofit. can u please help me
#Multipart
#POST("click_and_post")
Call<ResponseBody> clicPost(
#Part ("click_and_post[image]") RequestBody file,
#Part ("click_and_post[category_id]") String category_id,
#Part ("click_and_post[brand_id]") String brand_id,
#Part ("click_and_post[location]") String location);
POst man
I am unable to send data can u help me
This is how you should implement this api
int size = youImagePathList.size();
MultipartBody.Part[] multipartImageList = new MultipartBody.Part[size];
if(size > 0) {
for (int i = 0; i < size; i++) {
File file = new File(notificationItemList.get(i).getImageEncoded());
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"), file);
multipartImageList[i] = MultipartBody.Part.createFormData(""click_and_post[image]"", file.getName(), surveyBody);
}
}
RequestBody category_id = RequestBody.create(MediaType.parse("multipart/form-data"), StringCategoryID);
RequestBody brand_id = RequestBody.create(MediaType.parse("multipart/form-data"), StringBrandId);
RequestBody location = RequestBody.create(MediaType.parse("multipart/form-data"), StringLocation);
#Multipart
#POST("click_and_post")
Call<ResponseBody> clicPost(
#Header("Authorization") String authorization, // if there is headers
#Part MultipartBody.Part[] multipartImageList,
#Part("click_and_post[category_id]") RequestBody category_id,
#Part("click_and_post[brand_id]") RequestBody brand_id,
#Part("click_and_post[location]") RequestBody location);

Multiple image uploading using multipart retrofit or volley

Hi Can any one Please help me out in uploading multiple images selected from gallery,
parameter is 'images' as array list
I have tried with this but no response can any one help me out..
This is my request body :
MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
MultipartBody.Builder mRequestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
if (Imagepaths.size() > 0) {
for(String path:Imagepaths) {
File file = new File(path);
mediaType = path.endsWith("png") ?
MediaType.parse("image/png") : MediaType.parse("image/jpeg");
RequestBody imageBody = RequestBody.create(mediaType, file);
mRequestBody.addFormDataPart("images", file.getName(), imageBody);
}
}
RequestBody rb = mRequestBody.build();
This is the retrofit call :
#Multipart
#POST("upload_images/")
Call<ResponseBody> retrofitImageUpload(#Header("Authorization") String auth,
#Header("Content-Type") String contentType,
#Part("images") RequestBody req);

Retrofit - Combining Integer arraylist with Image file

Requirement is to upload image along with plain text and plain data has Arraylist of integers.
I am using #PartMap for plain data
For image part here is my code
imageFile = new File(imagePath);
imageBody = RequestBody.create(MediaType.parse("image/*"), imageFile);
multipartImageBody = MultipartBody.Part.createFormData("file_name", imageFile.getName(), imageBody);
For plain data
userIdBody = RequestBody.create(MediaType.parse("text/plain"), userId);
customerTypeBody = RequestBody.create(MediaType.parse("text/plain"), typeOfCustomer);
Combining plain data
HashMap<String, RequestBody> partMap = new HashMap<>();
partMap.put("userId", userIdBody);
partMap.put("customer_type", customerTypeBody);
The request
#POST<T> methodName(#PartMap Map<String, RequestBody> params, #Part MultipartBody.Part imageParam);
Issue occurs if i try to add integer listarray as Requestbody, the data is converted to string which server fails to parse rather we should be sending correct data from app side itself
What i tried
RequestBody.create(Mediatype,byte[])
Requestbody has this method which accepts our data as byte array,i converted arraylist to byte array but result was not as expected.
Is there any other possibility that i should try?
Converting from int[] to byte[] sounds like endianess issue. You should check in which endianess the server accepts the data and see if your conversion code is using the same endianess. You can use ByteBuffer to do the conversion, it has the order() method to specify endianess.
I haven't had any issues with retrofit's RequestBody.create myself, so I suspect this is the issue here.
Use it like this is the interface part
#Multipart
#POST("your/link")
Call<SuccessMessage> yourMethod(#Part MultipartBody.Part image,
#Part MultipartBody.Part[] data);//here you can use partmap also
and here is how it is used
MultipartBody.Part img = RequestHelper.multiPartBobyPart(image, "image");
MultipartBody.Part[] parts = new MultipartBody.Part[size];
for (int i = 0; i < size; i++) {
parts[i] = RequestHelper.multiPartBobyPart(yourStringArrayList.get(i), "var[]");
}
Call<SuccessMessage> call = mNetworkInterface.applyForDomesticJob(img, parts);
call.enqueue(this);
And here is the request helper class
public final class RequestHelper {
public static MultipartBody.Part multiPartBobyPart(java.io.File file, String parameterName) {
return MultipartBody.Part.createFormData(parameterName, file == null ? "noFile" : file.getName(),
RequestBody.create(MediaType.parse("multipart/form-data"), file == null ? new java.io.File("") : file));
}
public static RequestBody getRequestBody(String parameter) {
return RequestBody.create(MediaType.parse("multipart/form-data"), parameter);
}
public static MultipartBody.Part multiPartBobyPart(String data, String parameterName) {
return MultipartBody.Part.createFormData(parameterName, data);
}
}
use this link for more detailed information

Retrofit #body with #multipart having Issue

Image Multipart in class type object.
case 1. (Which I had done)
Service params:
{"id":"1","name":"vishal","image/file":""}
At that time my API of Retrofit
#Multipart
#POST("webservice")
Call<SignUpResp> loadSignupMultipart(#Part("description") RequestBody description, #Part MultipartBody.Part file, #QueryMap HashMap<String, String> params);
case 2. (Where I have Problem) with #Body class<UploadwithImage>
{
"methodName":"submitLevel1Part2Icon",
"userid":"150",
"headerData":{
"fiction":{
"icon_type":"1",
"icon_id":"3"},
"nonfiction":{
"icon_type":"2",
"icon_id":"4"},
"relation":{
"icon_type":"3",
"icon_id":"0",
"name":"Ronak",
"relative_image":"<File>",
"relation_id":"3"},
"self":{
"icon_type":"4",
"icon_id":"0"}
}
}
I am trying this API
#Multipart
#POST("webservice")
Call<SubmitLevel1Part2IconResp> loadLevel1halfIconswithImage(#Part("description") RequestBody description, #Part MultipartBody.Part file, #Body UploadwithImage uploadImage);
Java side
/**
* code for multipart
*/
// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), fileUpload);
// MultipartBody.Part is used to send also the actual filename
MultipartBody.Part body = MultipartBody.Part.createFormData("methodName[headerData][relation][relative_image]", fileUpload.getName(), requestFile);
// add another part within the multipart request
String descriptionString = "hello, this is description speaking";
RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
call = service.loadLevel1halfIconswithImage(description, body, levelOneHalfIcons);
I don't know why but it returns error like:
"#Body parameters cannot be used with form or multi-part encoding"
Any Help would Be Appreciated.
Change your method to
#Multipart
#POST("users/{id}/user_photos")
Call<models.UploadResponse> uploadPhoto(#Path("id") int userId, #PartMap Map<String, RequestBody> params);
Now to create your request parameters,
//All the String parameters, you have to put like
Map<String, RequestBody> map = new HashMap<>();
map.put("methodName", toRequestBody(methodName));
map.put("userid", toRequestBody(userId));
map.put("relation", toRequestBody(relation));
map.put("icon_type", toRequestBody(iconType));
map.put("icon_id", toRequestBody(iconId));
map.put("name", toRequestBody(name));
map.put("relation_id", toRequestBody(relationId));
//To put your image file you have to do
File file = new File("file_name");
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
map.put("relative_image\"; filename=\"some_file_name.png\"", fileBody);
// This method converts String to RequestBody
public static RequestBody toRequestBody (String value) {
RequestBody body = RequestBody.create(MediaType.parse("text/plain"), value);
return body ;
}
//To send your request
call = service.loadLevel1halfIconswithImage(description, params);
In case you do not want to use PartMap, you can simply pass them as parameters. Check my answer https://stackoverflow.com/a/37052548/1320616 to get some clue on sending image file with request.
As simple way, I have done like this:
I have tested by changing
Call<Result> resultCall = service.uploadImage(body);
to
Call<Result> resultCall = service.uploadImage(body, result); where result is
Result.java class (Response) of my API:
public class Result {
#SerializedName("result")
#Expose
private String result;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#SerializedName("value")
#Expose
private String value;
/**
* #return The result
*/
public String getResult() {
return result;
}
/**
* #param result The result
*/
public void setResult(String result) {
this.result = result;
}
}
and created object like:
Result result = new Result();
result.setResult("success");
result.setValue("my value");
You can change your class as per your need then pass object when you send request. So your ApiService class will be like:
ApiService.java
/**
* #author Pratik Butani on 23/4/16.
*/
public interface ApiService {
/*
Retrofit get annotation with our URL
And our method that will return us the List of Contacts
*/
#Multipart
#POST("upload.php")
Call<Result> uploadImage(#Part MultipartBody.Part file, #Part("result") Result result);
}
and My PHP code is:
<?php
$file_path = "";
$var = $_POST['result']; //here I m getting JSON
$file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) {
$result = array("result" => "success", "value" => $var);
} else{
$result = array("result" => "error");
}
echo json_encode($result);
?>
Hope it will helps you. Thank you.
You can also use a Map with RequestBody as value and string as keys to add parameters and you can send this using Multipart and PartMap.
Check the following code, hope it will help :
#Multipart
#POST("/add")
Call<ResponseBody> addDocument(#PartMap Map<String,RequestBody> params);
Map<String, RequestBody> map = new HashMap<>();
map.put("user_id", RequestBody.create(MediaType.parse("multipart/form-data"), SessionManager.getInstance().getCurrentUserId()));
map.put("doc_name", RequestBody.create(MediaType.parse("multipart/form-data"), CommonUtils.removeExtension(textFile.getName())));
map.put("doc_category", RequestBody.create(MediaType.parse("multipart/form-data"), category));
map.put("doc_image_file", RequestBody.create(MediaType.parse("multipart/form-data"), imageFile));
map.put("doc_text_content", RequestBody.create(MediaType.parse("multipart/form-data"), body));
map.put("doc_update_time", RequestBody.create(MediaType.parse("multipart/form-data"), "" + new Date(textFile.lastModified())));
We can add all request parameter in multipart body builder with specified type like in below one image file. I have set media type parse multipart/form-data and some other parameter I have set media type parse text/plain. This builder will build to make Multipart Body and can send by using body annotation in multipart body.
#Multipart
#POST("user/update")
Call<ResponseBody> addDocument(##Part MultipartBody file);
final MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
requestBodyBuilder.addFormDataPart("doc_image_file", imageFile.getName(),
RequestBody.create(MediaType.parse("multipart/form-data"), imageFile));
requestBodyBuilder.addFormDataPart("user_id", null, RequestBody.create(MediaType.parse("text/plain"),"12"));
requestBodyBuilder.addFormDataPart("doc_name", null, RequestBody.create(MediaType.parse("text/plain"),"myfile"));
requestBodyBuilder.addFormDataPart("doc_category", null, RequestBody.create(MediaType.parse("text/plain"),category));
requestBodyBuilder.addFormDataPart("doc_image_file", imageFile.getName(),RequestBody.create(MediaType.parse("multipart/form-data"),imageFile));
requestBodyBuilder.addFormDataPart("doc_text_content", null, RequestBody.create(MediaType.parse("text/plain"),body));
RequestBody multipartBody = requestBodyBuilder.build();
Here is my json request format is :
{
"task":{
"category_id":"1",
"price":"10",
"description":"1",
"task_videos_attributes":[
{
"link":"video file goes here",
"size":"100x100"
}
]
}
}
// my request becomes
HashMap<String, RequestBody> task = new HashMap();
task.put("task[category_id]", createPartFromString(categoryId));
task.put("task[price]", createPartFromString("" + etPrice.getText().toString()));
task.put("task[description]", createPartFromString("" + etDescription.getText().toString()));
// for videos file list
final List<MultipartBody.Part> body = new ArrayList<>();
for (int i = 0; i < videos.size(); i++) {
task.put("task[task_videos_attributes][" + i+ "][size]", createPartFromString("100x100"));
File videoFile = new File(videos.get(i));
RequestBody requestBody = RequestBody.create(MediaType.parse("video/mp4"), videoFile);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("task[task_videos_attributes][" + i + "][link]", videoFile.getName(), requestBody);
body.add(fileToUpload);
}
// here is a final call
new RestClient(this).getInstance().get().postTask(body, task).enqueue(callback);
// This function converts my string to request body
#NonNull
private RequestBody createPartFromString(String descriptionString) {
if (descriptionString == null)
return RequestBody.create(MultipartBody.FORM, "");
return RequestBody.create(
MultipartBody.FORM, descriptionString);
}
Hope this helps you...
Just follow how the web browser is doing multipart. They put nested keys in "[]" and give key to the images too.
Call<SubmitLevel1Part2IconResp> loadLevel1halfIconswithImage(#Part("headerdata[relation][icon_type]") RequestBody icon_type, #Part("headerdata[relation][name]") RequestBody name, #Part MultipartBody.Part file);
And then in java
// MultipartBody.Part is used to send also the actual filename
MultipartBody.Part body = MultipartBody.Part.createFormData("headerdata[relation][relative_image]", fileUpload.getName(), requestFile);
call = service.loadLevel1halfIconswithImage(icon_type, name, body);
https://www.linkedin.com/pulse/retrofit-2-how-upload-multiple-files-server-mahesh-gawale
I guess the best answer to this question can be found here. It worked perfectly for me.
This is the example of uploading an array of files using retrofit in Android.
This is how the service will look like
public interface ApiService {
#POST("/event/store")
Call<ResModel> event_store(#Body RequestBody file);
}
This is how the Client class look like
public class ApiClient {
public static final String API_BASE_URL = "api base url";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());
public static ApiService createService(Class<ApiService> serviceClass)
{
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
Upload like this in activity or fragment or where you want
ApiService service = ApiClient.createService(ApiService.class);
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("event_name", "xyz");
builder.addFormDataPart("desc", "Lorem ipsum");
// Single Image
builder.addFormDataPart("files",file1.getName(),RequestBody.create(MediaType.parse("image/*"), file1));
// Multiple Images
for (int i = 0; i <filePaths.size() ; i++) {
File file = new File(filePaths.get(i));
RequestBody requestImage = RequestBody.create(MediaType.parse("multipart/form-data"), file);
builder.addFormDataPart("event_images[]", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
}
MultipartBody requestBody = builder.build();
Call<ResModel> call = service.event_store(requestBody);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(getBaseContext(),"All fine",Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(getBaseContext(),t.getMessage(),Toast.LENGTH_SHORT).show();
}
});
Note: filePaths.size() is a Arraylist of pickup Images Paths.
I hope this post is useful to you. kindly share your feedback as a comment here.
this works for me.
What I did was add every additional params using:
MultipartBody.Part Partname = MultipartBody.Part.createFormData("ParamName", "Value");
Mabe you don't need to create another body, but just add others params apart from the file or whatever you are sending. finally at the interface I put as a params every bodypart that I need.
#Multipart
#POST("api/service/uploadVideo")
Call<ResponseBody> uploadVideoToServer(
#Part MultipartBody.Part video,
#Part MultipartBody.Part param2,
#Part MultipartBody.Part param3 ....
);

Categories

Resources