Following API I called for Editing User Profile . I have to send user profile picture so I used multipart in API .
#Multipart
#POST(ApiURLs.EDIT_USER_PROFILE)
Call<EditProfileModel> EditUserProfile (#Part("user_id) String userId ,
#Part("user_name") String userName ,
#Part("language_id") String languageId ,
#Part("state_id") String stateId ,
#Part MultipartBody.Part
profilePicture);
When Service called the requested parameters would be like
"user_id" : ""23""
"user_name" : ""Keval Shukla""
"language_id": ""27""
"state_id" : "53""
how do i remove that double quote using MultiPart ?
It must be like -
#Multipart
#POST(ApiURLs.EDIT_USER_PROFILE)
Call<EditProfileModel> EditUserProfile (
#Part("user_id") RequestBody userId ,
#Part("user_name") RequestBody userName ,
#Part("language_id") RequestBody languageId ,
#Part("state_id") RequestBody stateId ,
#Part RequestBody profilePicture);
And, to create requestBody,
File file = new File(imageURI.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file); // File requestBody
RequestBody userName = RequestBody.create(MediaType.parse("text/plain"), userNameSTRING); // String requestBody
You can send parameters other than file as RequestBody.
#Multipart
#POST(ApiURLs.EDIT_USER_PROFILE)
Call<EditProfileModel> EditUserProfile (#Part("user_id) RequestBody userId ,
#Part("user_name") RequestBody userName ,
#Part("language_id") RequestBody languageId ,
#Part("state_id") RequestBody stateId ,
#Part MultipartBody.Part profilePicture);
To Convert String to RequestBody:
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), userName); // Here userName is String
You are doing it wrong way, when you are using MultiPart as body type you have to specify body type of each request parameter.
For example, you are sending file(image,video etc.) and string parameters. So you need to specify all the parameters and convert it to specific body type.
You need to divide parameters into two parts,
1) MultipartBody - For media file
2) RequestBody - For other string or other data type parameters
e.g.
/*Create API Method*/
#Multipart
#POST("apiurl")
Call<Object> callMethodName(#Part("mobile_no") RequestBody mobile_no, /*String param */
#Part("password") RequestBody password, /*String param */
#Part MultipartBody.Part profile_img /*file param */);
I have define Parse type as multipart/form-data, you can define as according to your requirements,
public static final String MULTIPART_TYPE = "multipart/form-data";
Now create request parameters as below,
/* Adding String Params*/
RequestBody reqNumber = RequestBody.create(MediaType.parse(Constants.MULTIPART_TYPE), number.toString());
RequestBody reqPass = RequestBody.create(MediaType.parse(Constants.MULTIPART_TYPE), pass.toString());
/* Adding File*/
File file = new File(selectedImagePath);
RequestBody requestFile = RequestBody.create(MediaType.parse(Constants.MULTIPART_TYPE), file);
bodyFile = MultipartBody.Part.createFormData("profile_img", file.getName(), requestFile);
As last step, you need to pass request parameter to API call method as below, so it can identify parameters and send it to server.
/* Call API Method */
RestClient.getApiClient().callMethodName(reqNumber, reqPass, bodyFile);
Use RequestBody instead of String.
#Part("user_id") RequestBody user_id,
To call it
String userId= "123456";
RequestBody id =
RequestBody.create(
okhttp3.MultipartBody.FORM, userId);
Related
I am hitting an api with put request and pass Multipart data. Here is my interface:
#Multipart
#PUT("profile")
Call<ProfileSetupResponse> vendorProfile1(
#Header("access-token") String token,
#Part("businessName") RequestBody businessName,
#Part("step") RequestBody step,
#Part MultipartBody.Part image,
#Query("categories[]") List<String> categories,
#Part("country") RequestBody country,
#Part("contact") RequestBody contact,
#Part("aboutUs") RequestBody aboutUs,
#Part("businessDetail") RequestBody businessDetail,
#Part("businessEmail") RequestBody businessEmail,
#Query("tags[]") List<String> tags
);
I am getting the "java.lang.illegalStateException:Expected a string but was BEGIN_ARRAY at line 1 column 591" exception in the response from server.
Here is my method to pass data to server:
Call<ProfileSetupResponse> call = RetrofitClient.getInstance().getApi().vendorProfile1("Token",
bName, bStep, filePart, categories, bCountry, bContact, bAboutUs, bDetail, bEmail, tags);
Here Categories and Tags are ArrayList<>.
I am new to working with Retrofit please someone help.
Update to Question:
RequestBody bName = RequestBody.create(MediaType.parse("text/plain"), "businessName");
RequestBody bCountry = RequestBody.create(MediaType.parse("text/plain"), "businessCountry");
RequestBody bAboutUs = RequestBody.create(MediaType.parse("text/plain"), "businessAboutUs");
RequestBody bDetail = RequestBody.create(MediaType.parse("text/plain"), "businessDetail");
RequestBody bEmail = RequestBody.create(MediaType.parse("text/plain"), "businessEmail");
RequestBody bContact = RequestBody.create(MediaType.parse("text/plain"), "businessContact");
RequestBody bStep = RequestBody.create(MediaType.parse("text/plain"), "1");
I am not sending arraylists or image just to check the response, but still getting the same error.
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 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);
Ok, before you start saying that it's a duplicate and so on...
I have tried all ways I found on slack / documentations and it didn't help me out at all...and I just can't figure out what the problem is
So, these are last 2 ways I tried to make the request
final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
//RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), loadImageFile);
//MultipartBody.Part filePart = MultipartBody.Part.createFormData("picture", loadImageFile.getName(), reqFile);
//RequestBody filename =
RequestBody.create(MediaType.parse("text/plain"),loadImageFile.getName());
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"),
loadImageFile);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file",
loadImageFile.getName(), requestBody);
The commented parts is a way, and the other lines is the way I am doing it now..
Here I have the interface
#Multipart
#POST(RestClient.API_REGISTER_URL)
Call<ResponseBody> register(#Query("name") String name, #Query("email") String email,
#Query("password") String password, #Query("location") String location,
#Query("latitude") double latitude, #Query("longitude") double longitude,
#Query("gender") String gender, #Part MultipartBody.Part picture,
#Part("picture") RequestBody file,
#Query("device_uuid") String device_uuid, #Query("device_os") String device_os,
#Query("push_token") String push_token, #Query("api_key") String user);
To be honnest, I simply can't figure out why it is not working..the response body from the server is "The picture must be an image" which makes me think that somehow it doesn't recognise the file I am sending
Any help would be apreciated, thanks .
EDIT
I changed the code a lil bit, another way I was trying to make it, and still something is not ok with this request...
RequestBody req = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("picture", loadImageFile.getName(), RequestBody.create( MultipartBody.FORM, loadImageFile))
.build();
MultipartBody.Part part = MultipartBody.Part.createFormData("picture", loadImageFile.getName(), req);
I'm using this code to send image to server with okhttp
final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
RequestBody req = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("branchCode", branchCode)
.addFormDataPart("upload", "profile.png", RequestBody.create(MEDIA_TYPE_PNG, file)).build();
Request request = new Request.Builder()
.url(URLs.UPLOAD_FILE)
.post(req)
.build();
Maybe problem occurs in your server side ?
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