Is it possible to send #Fields with multipart in retrofit2? - android

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);

Related

Why can't I upload an image and data with retrofit2?

Regards, I have to upload this data.
postman
And I have this code.
Customer Creation
public BeeMappingClient(String url){
retrofit= new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
conexion=retrofit.create(Conexion.class);
}
Interface
#Multipart
#POST("task")
Call<ResponsetTask> API_Task(#Header("Authorization") String key,
#Part MultipartBody.Part multipartImage,
#Part("message") RequestBody message ,
#Part("filecomment") RequestBody filecomment,
#Part("api_token") RequestBody api_token,
#Part("user_id") RequestBody user_id);
And call
File file=new File(path);
MultipartBody.Part[] multipartImageList = new MultipartBody.Part[1];
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"), file);
multipartImageList[0] = MultipartBody.Part.createFormData("image", "image.jpg", surveyBody);
RequestBody message = RequestBody.create(MediaType.parse("message"), Constantes.MESSAGE);
RequestBody filecomment = RequestBody.create(MediaType.parse("filecomment"), Constantes.FILECOMMENT);
RequestBody api_token = RequestBody.create(MediaType.parse("api_token"),Constantes.api_token);
RequestBody user_id = RequestBody.create(MediaType.parse("user_id"), Integer.toString(Constantes.id));
Call<ResponsetTask> call = conexion.API_Task(Constantes.AUTH,multipartImageList[0],message,filecomment,api_token,user_id);
call.enqueue(new Callback<ResponsetTask>() {
#Override
public void onResponse(Call<ResponsetTask> call, Response<ResponsetTask> response) {
Constantes.api_task=response.body().getTaskId();
}
#Override
public void onFailure(Call<ResponsetTask> call, Throwable t) {
}
});
The problem is that it does nothing, if I do a debug all seems to be going well until it reaches the call.enqueu ... there I should enter OnResques or OnFailure but it does not just go to the end of the method as if it did not exist .
What should I do ?, this is the best method to upload this data ?.
I thank you in advance for any help or guidance you can give me.
Try this - for multipart request
In interface
#Multipart
#POST("task")
Call<ResponseBody> submitRegistration(#Part MultipartBody.Part body,
#Part("message") RequestBody message)
Pass values -
File file = new File(path);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
RequestBody message = RequestBody.create(MediaType.parse("text/plain"), Constantes.MESSAGE);
Call -
Call<ResponseBody> call = service.callApi(body,message);
RequestBody surveyBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
Replace "image/*" with "multipart/form-data"

is it possible to pass a single item as multipart using retrofit?

#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();
}
});

Android Retrofit 2 multipart always giving error 400

I'm trying to send one image and somes string through retrofit, but it's not working, I'm always getting a 400. My app is already using webservices such as GET or POST without troubles, I assume that my probleme is with the upload...
I used that explanations and the github of retrofit.
My idea here is to create a new Dish and sed it to my server, so most of the data are comming from InputTextField and the photo is taken by the camera using an Intent
First my interface for uploading
#Multipart
#POST("japronto/api/chef/dish/new")
Call<Dish> upload(#Part("name") RequestBody name, #Part("description") RequestBody description,#Part("disponibility") RequestBody disp,#Part("max") RequestBody max,#Part("price") RequestBody price, #Part MultipartBody.Part file);
My function to upload
public void onOK(){
RequestBody name = RequestBody.create( MediaType.parse("multipart/form-data"), this.name.getText().toString());
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), this.description.getText().toString());
RequestBody disp =
RequestBody.create(
MediaType.parse("multipart/form-data"), Integer.toString(this.TorF));
RequestBody max =
RequestBody.create(
MediaType.parse("multipart/form-data"), this.max.getText().toString());
RequestBody price =
RequestBody.create(
MediaType.parse("multipart/form-data"), this.price.getText().toString());
File nImg = new File(folderImg, imgName);
RequestBody rqFile =
RequestBody.create(MediaType.parse("multipart/form-data"), nImg);
MultipartBody.Part body =
MultipartBody.Part.createFormData("picture", nImg.getName(), rqFile);
ApiService apiService = ApiManager.createService(ApiService.class, this.chef.getPseudo(), this.chef.getPassword());
Call<Dish> call = apiService.upload(name, description, disp, max, price, body);
call.enqueue(new Callback<Dish>() {
#Override
public void onResponse(Call<Dish> call, Response<Dish> response) {
Dish d = response.body();
Log.d(TAG, "onResponse: "+d.getName());
}
#Override
public void onFailure(Call<Dish> call, Throwable t) {
}
});
}
My view on the server
#app.route('/japronto/api/chef/dish/new', methods=['POST'])
def upload():
if request.method == 'POST':
if 'file' not in request.files:
print 'pbs'
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
print filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return {'name':filename}
return{'name':'erro'}
Any ideas?
Try this
#Multipart
#POST("japronto/api/chef/dish/new")
Call<Dish> upload(#Part("name") RequestBody name, #Part("description") RequestBody description,#Part("disponibility") RequestBody disp,#Part("max") RequestBody max,#Part("price") RequestBody price, #Part("ImageNameHere\"; filename=\"image.png\" ") RequestBody image);
File nImg = new File(folderImg, imgName);
RequestBody rqFile = RequestBody.create(MediaType.parse("image/png"), nImg);
check these links
Link 1 Link 2 Link 3

Send image with Retrofit2

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.

Error uploading a file using Retrofit 2

I'm trying to upload a file (picture) to the server using Retrofit 2. I'm following that tutorial which seems pretty easy at first, but didn't work in my case...
When I call the API function, i'm always getting this error:
W/System.err: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
W/System.err: at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:190)
W/System.err: at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)
W/System.err: at retrofit2.Retrofit$1.invoke(Retrofit.java:145)
W/System.err: at java.lang.reflect.Proxy.invoke(Proxy.java:393)
W/System.err: at com.plante.android.cobalt.fragment.FragmentIncidentPlan.uploadFile(FragmentIncidentPlan.java:575)
Here is my API call:
#Multipart
#POST(Constants.URL_UPLOAD)
Call<ResponseBody> upload(#Part RequestBody description,
#Part MultipartBody.Part file);
Here is the method I use to upload a file:
private void uploadFile(String path) {
// create upload service client
// use the FileUtils to get the actual file by uri
File file = new File(path);
Log.e(TAG, file.getAbsolutePath());
// create RequestBody instance from file
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
String descriptionString = "hello, this is description speaking";
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), descriptionString);
// finally, execute the request
Call<ResponseBody> call = cobaltServices.upload(description, body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
}
The Exceptions says that the first #Part doesn't needs a name in the annotation.
#Multipart
#POST(Constants.URL_UPLOAD)
Call<ResponseBody> upload(#Part RequestBody description,
#Part MultipartBody.Part file);
I fix my issue using this link : https://github.com/square/retrofit/issues/1063#issuecomment-145920568
This is the solution of the problem:
#Multipart
#POST ("/api/Events/editevent")
Call<Event> editEvent (#PartMap Map<String, RequestBody> params);
I call it by following way.
Map<String, RequestBody> map = new HashMap<>();
map.put("Id", AZUtils.toRequestBody(eventId));
map.put("Name", AZUtils.toRequestBody(titleView.getValue()));
if (imageUri != null) {
File file = new File(imageUri.getPath());
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
map.put("file\"; filename=\"pp.png\"", fileBody);
}
Call<Event> call = api.editEvent(map);
call.enqueue(new Callback<Event>() { }
The method toRequestBody just converts String into RequestBody
public static RequestBody toRequestBody (String value) {
RequestBody body = RequestBody.create(MediaType.parse("text/plain"), value);
return body ;
}

Categories

Resources