#Multipart
#POST("/api/add-deal/")
public void addDeal(#Body Deal deal, #Part("image")TypedFile image,Callback<Response> callback);
I want to send only the image as multipart and the rest as is.Is there any possible way ? Even I tried to add TypedFile inside my Deal model but unable to annotate with #part
Yes, it is possible with Partmap annotation using hash map. For example-
#Multipart
#POST("/api/add-deal/")
Call<Response> addDeal(#PartMap
HashMap<String, RequestBody> hashMap);
In hashMap you can add no of url parameters as key and set your values using RequestBody class type. see how to convert String and Image to RequestBody.
public static RequestBody ImageToRequestBody(File file) { //for image file to request body
return RequestBody.create(MediaType.parse("image/*"),file);
}
public static RequestBody StringToRequestBody(String string){ // for string to request body
return RequestBody.create(MediaType.parse("text/plain"),string);
}
add params to hashmap-
hashMap.put("photo",ImageToRequestBody(imageFile)); //your imageFile to Request body.
hashMap.put("user_id",StringToRequestBody("113"));
//calling addDeal method
apiInterface.addDeal(hashMap);
Hope this helpful.
It seems that you can send your #Body as TypedString.
For example, convert your "#Body Deal deal" into JSON String, and send it as TypedString.
Details: How to send multipart/form-data with Retrofit?
#Multipart
#POST("/api/v1/articles/")
Observable<Response> uploadFile(#Part("author") TypedString authorString,
#Part("photo") TypedFile photoFile);
This worked for me: POST Multipart Form Data using Retrofit 2.0 including image
public interface ApiInterface {
#Multipart
#POST("/api/Accounts/editaccount")
Call<User> editUser (#Header("Authorization") String authorization, #Part("file\"; filename=\"pp.png\" ") RequestBody file , #Part("FirstName") RequestBody fname, #Part("Id") RequestBody id);
}
File file = new File(imageUri.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), firstNameField.getText().toString());
RequestBody id = RequestBody.create(MediaType.parse("text/plain"), AZUtils.getUserId(this));
Call<User> call = client.editUser(AZUtils.getToken(this), fbody, name, id);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(retrofit.Response<User> response, Retrofit retrofit) {
AZUtils.printObject(response.body());
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
Related
I'm using retrofit2, i was sending data through it using #FormUrlEncoded because everything was as a string even images but i faced some errors when i send collection of images as strings, so i changes to multipart.
Now i'm facing problem that i can't send #Field of string with multipart.
So, how i can solve this problem without using RequestBody for every string?
here's my code
#Multipart
#POST("/androidfiles/insertNews.php")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part file, #Part("name") RequestBody name,
#Field("tArabic") String arabicTitle,
#Field("tEnglish") String englishTitle,
#Field("tRussian") String russianTitle,
#Field("tItalian") String italianTitle,
#Field("dArabic") String arabicDescription,
#Field("dEnglish") String englishDescription,
#Field("dRussian") String russianDescription,
#Field("dItalian") String italianDescription);
and here.
private void insertNews(Uri uri){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ServiceConstants.URL)
.build();
File file = FileUtil.getFile(this, uri);
RequestBody mFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", file.getName(), mFile);
RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), file.getName());
ApiConfig apiConfig = retrofit.create(ApiConfig.class);
Call<ResponseBody> addNews = apiConfig.uploadImage(fileToUpload,
filename,
etArabicTitle.getText().toString(),
etEnglishTitle.getText().toString(),
etRussianTitle.getText().toString(),
etItalianTitle.getText().toString(),
etArabicDescription.getText().toString(),
etEnglishDescription.getText().toString(),
etRussianDescription.getText().toString(),
etItalianDescription.getText().toString());
addNews.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(News.this, "success" + "\n" + response.message(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(News.this,Menu.class);
startActivity(intent);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(News.this, "fail" + t.getMessage(), Toast.LENGTH_SHORT).show();
t.printStackTrace();
}
});
}
When using multipart requests using Retrofit, you can pass extra parameters using #Part annotation having RequestBody fields for additional parameters.
So, You can pass it as RequestBody type for all parameters except multipart body like below :
#Multipart
#POST("/androidfiles/insertNews.php")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part file,
#Part("name") RequestBody name,
#Part("tArabic") RequestBody arabicTitle,
#Part("tEnglish") RequestBody englishTitle,
#Part("tRussian") RequestBody russianTitle,
#Part("tItalian") RequestBody italianTitle,
#Part("dArabic") RequestBody arabicDescription,
#Part("dEnglish") RequestBody englishDescription,
#Part("dRussian") RequestBody russianDescription,
#Part("dItalian") RequestBody italianDescription);
Now, for calling such API; you'll need to pass it by creating RequestBody for additional parameters as MIME Type text/plain using syntax (i.e. RequestBody.create(MediaType.parse("text/plain"), your variable goes here))
During API build up, you can pass call it as:
Call<ResponseBody> addNews = apiConfig.uploadImage(fileToUpload,
filename,
RequestBody.create(MediaType.parse("text/plain"), etArabicTitle.getText().toString()), //This will make it as RequestBody to pass it along image/files.
RequestBody.create(MediaType.parse("text/plain"), etEnglishTitle.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etRussianTitle.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etItalianTitle.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etArabicDescription.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etEnglishDescription.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etRussianDescription.getText().toString()),
RequestBody.create(MediaType.parse("text/plain"), etItalianDescription.getText().toString()));
try changing #Field to #Part . like this :
#Multipart
#POST("/androidfiles/insertNews.php")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part file, #Part("name") RequestBody name,
#Part("tArabic") String arabicTitle,
#Part("tEnglish") String englishTitle,
#Part("tRussian") String russianTitle,
#Part("tItalian") String italianTitle,
#Part("dArabic") String arabicDescription,
#Part("dEnglish") String englishDescription,
#Part("dRussian") String russianDescription,
#Part("dItalian") String italianDescription);
I'm trying to upload an image to the server using Retrofit2, but am very unsure on how to do so.
The documentation left me a bit confused and I have tried the solution mentioned here, but it did not work for me.
Here is the code snippet I'm currently using, which doesn't send anything to the server:
// Service
#Multipart
#POST("0.1/gallery/{galleryId}/addImage/")
Call<ResponseBody> addImage(#Path("galleryId") String galleryId, #Part MultipartBody.Part image);
//Call
MultipartBody.Part imagePart = MultipartBody.Part.createFormData("image", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
Call<ResponseBody> call = service. addImage("1234567890", imagePart);
However, I'm able to do it just fine using Retrofit 1.9 with a TypedFile.
Am I doing something wrong or Retrofit2 has some issue with this sort of thing?
I've struggled for a while with this to, I ended up with this solution to finally make it work... Hopes it helps:
Map<String, RequestBody> map = new HashMap<>();
map.put("Id",Utils.toRequestBody("0"));
map.put("Name",Utils.toRequestBody("example"));
String types = path.substring((path.length() - 3), (path.length()));
File file = new File(pathOfYourFile);
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpg"), file);
map.put("file\"; filename=\"cobalt." + types + "\"", fileBody);
Call<ResponseBody> call = greenServices.upload(map);
In the greenServices interface:
#Multipart
#POST(Constants.URL_UPLOAD)
Observable<Response<ResponseBody>> uploadNew(#PartMap Map<String, RequestBody> params);
hi please check how we can send image in retrofit2.In form of part you need to send image and other data as well.
public interface ApiInterface {
#Multipart
#POST("0.1/gallery/{galleryId}/addImage/")
Call<User> checkapi (#Part("file\"; filename=\"pp.png\" ") RequestBody file , #Part("FirstName") RequestBody fname, #Part("Id") RequestBody id);
}
File file = new File(imageUri.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), firstNameField.getText().toString());
RequestBody id = RequestBody.create(MediaType.parse("text/plain"), AZUtils.getUserId(this));
Call<User> call = client.editUser(AZUtils.getToken(this), fbody, name, id);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(retrofit.Response<User> response, Retrofit retrofit) {
AZUtils.printObject(response.body());
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
Thanks hope this will help you.
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 ....
);
I used to send POST request to server with Retrofit2:
#POST("goals")
Call<Void> postGoal(#Body Goal goal);
where Goal was object with some String/Integer fields.
Now I need to add a photo file there.
I know I need to switch to use Multipart:
#Multipart
#POST("goals")
Call<Void> postGoal(
#Part("picture") RequestBody picture
);
//...
//Instantaining picture
RequestBody.create(MediaType.parse("image/*"), path)
But how am I supposed to add previous fields ? In particular is there a way to add whole Goal object without dividing it for fields ?
for sending json and file you can follow something like this.
#Multipart
#POST("goals")
Call<JsonModel> postGoal(#Part MultipartBody.Part file, #Part("json") RequestBody json);
Now convert your Object which you want to send as a json into json using Gson.
like this.
String json = new Gson().toJson(new Goal());
File file = new File(path);
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("picture", file.getName(), requestFile);
// add another part within the multipart request
RequestBody jsonBody=
RequestBody.create(
MediaType.parse("multipart/form-data"), json);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RestApi api = retrofit.create(RestApi.class);
Call<ResponseBody> call = api.upload(jsonBody, body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("onResponse: ", "success");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("onFailure: ", t.getLocalizedMessage());
}
});
You can add #Part with you goal like this
#Multipart
#POST("goals")
Call<Void> postGoal(
#Part("picture") RequestBody picture,
#Part("goal") RequestBody goal
);
//...
//Instantaining picture
RequestBody.create(MediaType.parse("image/*"), path)
You can find more details : retrofit-2-how-to-upload-files-to-server
I'm trying to upload an image along with a pojo model with username and password, but how do i use the multipart to add both, here is my code but isn't working:
EndpointInterface loginService = ServiceAuthGenerator.createService(EndpointInterface.class);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
Call<String> call = loginService.singup(requestBody,us);
call.enqueue(new Callback<String>() {#Override
public void onResponse(Response<String> response, Retrofit retrofit) {
}
#Override
public void onFailure(Throwable t) {
}
});
us is my pojo model and it contains the user and the password.
this is the API interface:
#Multipart
#POST("reg/")
Call<String> singup(
#Part("myfile\"; filename=\"image.png\" ") RequestBody file,
#Part("User") User user);
can anyone explain what im doing wrong and how to fix it please?
Should you use MediaType.parse("image/*") instead MediaType.parse("multipart/form-data")? It is because you upload image later.
You might be better off using the multipart builder for the request body than the #Multipart annotation.
RequestBody body = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("myFile", "image.png", RequestBody.create(MediaType.parse("image/jpg"), new File(picture.getLocalPath())))
.addFormDataPart("user", gson.toJson(user))
.build();
#POST("reg/")
Call<String> singup(#Body RequestBody image);