I am using Retrofit to upload images to my server. Here I need to upload multiple images for a single key. I have tried with Postman web client it is working well. Here is a screenshot.
Here are the key value pairs for the request.
SurveyImage : [file1,file2,file3];
PropertyImage : file
DRA : jsonBody
I tried to do the same with Retrofit. but the images are not uploading to the server.Here is my code.
WebServicesAPI.java
public interface WebServicesAPI {
#Multipart
#POST(WebServices.UPLOAD_SURVEY)
Call<UploadSurveyResponseModel> uploadSurvey(#Part MultipartBody.Part surveyImage, #Part MultipartBody.Part propertyImage, #Part("DRA") RequestBody dra);
}
Here is the method for uploading the files.
private void requestUploadSurvey() {
File propertyImageFile = new File(surveyModel.getPropertyImagePath());
RequestBody propertyImage = RequestBody.create(MediaType.parse("image/*"), propertyImageFile);
MultipartBody.Part propertyImagePart = MultipartBody.Part.createFormData("PropertyImage", propertyImageFile.getName(), propertyImage);
JSONObject requestBody = getRequestBody();
RequestBody draBody = null;
try {
draBody = RequestBody.create(MediaType.parse("text/plain"), requestBody.toString(1));
Log.d(TAG, "requestUploadSurvey: RequestBody : " + requestBody.toString(1));
} catch (JSONException e) {
e.printStackTrace();
}
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
MultipartBody surveyImage = null;
for (SurveyModel.PictureModel model : surveyModel.getPicturesList()) {
File file = new File(model.getImagePath());
builder.addFormDataPart("SurveyImage", file.getName(),
RequestBody.create(MediaType.parse("image/*"), file));
}
surveyImage = builder.build();
final WebServicesAPI webServicesAPI = RetrofitManager.getInstance().getRetrofit().create(WebServicesAPI.class);
Call<UploadSurveyResponseModel> surveyResponse = null;
surveyResponse = webServicesAPI.uploadSurvey(MultipartBody.Part.createFormData("SurveyImage", "SurveyImage", surveyImage), propertyImagePart, draBody);
surveyResponse.enqueue(this);
Log.d(TAG, "requestUploadSurvey: sent the request");
}
Please help me with this.
We can use MultipartBody.Part array to upload an array of images to a single key.
Here is the solution
WebServicesAPI
#Multipart
#POST(WebServices.UPLOAD_SURVEY)
Call<UploadSurveyResponseModel> uploadSurvey(#Part MultipartBody.Part[] surveyImage,
#Part MultipartBody.Part propertyImage,
#Part("DRA") RequestBody dra);
Here is the method for uploading the files.
private void requestUploadSurvey () {
File propertyImageFile = new File(surveyModel.getPropertyImagePath());
RequestBody propertyImage = RequestBody.create(MediaType.parse("image/*"),
propertyImageFile);
MultipartBody.Part propertyImagePart = MultipartBody.Part.createFormData("PropertyImage",
propertyImageFile.getName(),
propertyImage);
MultipartBody.Part[] surveyImagesParts = new MultipartBody.Part[surveyModel.getPicturesList()
.size()];
for (int index = 0; index <
surveyModel.getPicturesList()
.size(); index++) {
Log.d(TAG,
"requestUploadSurvey: survey image " +
index +
" " +
surveyModel.getPicturesList()
.get(index)
.getImagePath());
File file = new File(surveyModel.getPicturesList()
.get(index)
.getImagePath());
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"),
file);
surveyImagesParts[index] = MultipartBody.Part.createFormData("SurveyImage",
file.getName(),
surveyBody);
}
final WebServicesAPI webServicesAPI = RetrofitManager.getInstance()
.getRetrofit()
.create(WebServicesAPI.class);
Call<UploadSurveyResponseModel> surveyResponse = null;
if (surveyImagesParts != null) {
surveyResponse = webServicesAPI.uploadSurvey(surveyImagesParts,
propertyImagePart,
draBody);
}
surveyResponse.enqueue(this);
}
I wasted a lot timing on accepted ans. but that didn't work in my case.
So after a lot of search i found this one. And its working 100% in my case.
private void uploadMultiFile() {
ArrayList<String> filePaths = new ArrayList<>();
filePaths.add("storage/emulated/0/DCIM/Camera/IMG_20170802_111432.jpg");
filePaths.add("storage/emulated/0/Pictures/WeLoveChat/587c4178e4b0060e66732576_294204376.jpg");
filePaths.add("storage/emulated/0/Pictures/WeLoveChat/594a2ea4e4b0d6df9153028d_265511791.jpg");
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("user_name", "Robert");
builder.addFormDataPart("email", "mobile.apps.pro.vn#gmail.com");
// Map is used to multipart the file using okhttp3.RequestBody
// Multiple Images
for (int i = 0; i < filePaths.size(); i++) {
File file = new File(filePaths.get(i));
builder.addFormDataPart("file[]", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
}
MultipartBody requestBody = builder.build();
Call<ResponseBody> call = uploadService.uploadMultiFile(requestBody);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(MainActivity.this, "Success " + response.message(), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d(TAG, "Error " + t.getMessage());
}
});
}
and this is interface
#POST("/upload_multi_files/MultiPartUpload.php")
Call<ResponseBody> uploadMultiFile(#Body RequestBody file);
Best solution ever I have tried
ApiInterface:
#Multipart
#POST("person/img")
Call<ResponseBody> upImageMany(#Part List<MultipartBody.Part> file);
Activity:
List<MultipartBody.Part> parts = new ArrayList<>();
for (int i=0; i < upFileList.size(); i++){
parts.add(prepareFilePart("my_file["+i+"]", upFileList.get(i)));
}
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri){
File file = new File(getPath(fileUri));
RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
return MultipartBody.Part.createFormData(partName, file.getName(),requestBody);
}
For a single key, you can use,
#POST("upload/images")
Observable<YourBaseResponse>
uploadMultipleImages(#Body RequestBody imagesBody);
And you can create RequestBody as follow,
public static MultipartBody buildMultipartForMultipleImages(Context context, List<MediaPreviewModel> allAddMediaImages) {
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
for (int index = 0; index < allAddMediaImages.size(); index++) {
builder.addFormDataPart("images", "image" + index, getRequestBodyForImages(context, allAddMediaImages.get(index).getUri()));
}
return builder.build();
}
where MediaPreviewModel is a POJO containing images details (URI, filename, extension, size, etc..)
Create request body as
public static RequestBody getRequestBodyForImages(Context context, Uri uri) {
File file = null;
try {
file = getFile(context, uri);
} catch (IOException e) {
e.printStackTrace();
}
File file1 = CompressFile.getCompressedImageFile(file, context);
RequestBody imageReqBody;
if (file1 != null) {
imageReqBody = RequestBody.create(file1, MediaType.parse("image/jpg"));
} else {
assert file != null;
imageReqBody = RequestBody.create(file, MediaType.parse("image/jpg"));
}
return imageReqBody;
}
Related
My target or my goal is to have a request like this so that it will succeed:
Now my current code looks like this:
WebApi client = ServiceGenerator.createService(WebApi.class);
final Call<BaseResponse<BookingInfoEntity>> call = client.startBooking(
WebUtilities.createPartFromString(SharePreferences.getUserId(context)),
WebUtilities.createPartFromString(""), //trainer_id
WebUtilities.createPartFromString(String.valueOf(listener.getTrainerTypesObject().get(0))), //train type
WebUtilities.createPartFromString(String.valueOf(hours)),
WebUtilities.createPartFromString(String.valueOf(payment_id)),
WebUtilities.createPartFromString(SharePreferences.getCityId(context)),
WebUtilities.createPartFromString(listener.getSelectedDate()));
}
public static RequestBody createPartFromString(String descriptionString) {
return RequestBody.create(okhttp3.MultipartBody.FORM, descriptionString);
}
#Multipart
#POST(START_BOOKING)
Call<BaseResponse<BookingInfoEntity>> startBooking(#Part("trainee_id") RequestBody trainee_id,
#Part("trainer_id") RequestBody trainer_id,
#Part("trainer_types[][trainer_type_id]")RequestBody train_type,
#Part("number_of_hours") RequestBody number_of_hours,
#Part("payment_type_id") RequestBody payment_type_id,
#Part("city_id") RequestBody city_id,
#Part("meeting_date") RequestBody meeting_date);
My problem is: How can i dynamically insert
trainer_types[][trainer_type_id],
like i want when i have 5 trainer type id,
how can i insert a 5 trainer_type_id in they key and set a value with it?
I just want to replicate the image above so that i can properly solve this value.
Your request should be like this:
#Multipart
#POST(START_BOOKING)
Call<BaseResponse<BookingInfoEntity>> startBooking(#Part("trainee_id") RequestBody trainee_id,
#Part("trainer_id") RequestBody trainer_id,
#Part List<MultipartBody.Part> train_type,
#Part("number_of_hours") RequestBody number_of_hours,
#Part("payment_type_id") RequestBody payment_type_id,
#Part("city_id") RequestBody city_id,
#Part("meeting_date") RequestBody meeting_date);
Create List of trainer_types for file types
#NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri, String file_type) {
File file;
if (file_type.contains("video")) {
file = new File(fileUri.getPath());
} else {
file = FileUtils.getFile(this, fileUri);
}
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part is used to send also the actual file name
return MultipartBody.Part.createFormData(partName, file.getName().replaceAll(" ", "%20"), requestFile);
}
Call API with multiple Same keys dientional arrays
private void startUploadingList(ArrayList<String> selectedItems1) {
List<MultipartBody.Part> parts = new ArrayList<>();
try {
for (int i = 0; i < selectedItems1.size(); i++) {
if (selectedItems1.get(i) != null) {
parts.add(prepareFilePart("trainer_types[][" + i + "]", Uri.parse(selectedItems1.get(i)), "image/png"));
}
}
RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), "Your Value");
// add another part within the multipart request
// finally, execute the request
Call<BaseResponse<BookingInfoEntity>> call = APIClient.getInterface().startBooking(description ,description ,parts, description,description ,description ,description );
call.enqueue(new Callback<BaseResponse<BookingInfoEntity>>() {
#Override
public void onResponse(Call<BaseResponse<BookingInfoEntity>> call, Response<BaseResponse<BookingInfoEntity>> response) {
Log.e("Upload", "success");
}
#Override
public void onFailure(Call<BaseResponse<BookingInfoEntity>> call, Throwable t) {
call.cancel();
Log.e("Upload error:", t.getMessage());
t.printStackTrace();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
I have a fragment where, I click on Browse Button and open file manager and select the file and send it to server via POST Retrofit2.
I get the success message 200. The file is listed in server but it wont open. The size is 1kb. So, I think the file is not properly uploaded.
Following is my code.
Where am I going wrong?
File origFile = new File(PathHolder);
String getDirPath = origFile.getParent();
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), getDirPath);
multipartBody = MultipartBody.Part.createFormData("uploadFiles",origFile.getName(),requestFile);
new UploadFileAsyncTask().execute();
And the async task is
protected notificationVO doInBackground(Void... params) {
notificationVO res;
WebserviceImpl webservices = new WebserviceImpl();
res = webservices.notifyAttachment(token,multipartBody, getContext());
Log.e("File","browse uploaded");
return res;
}
Api
#Multipart
#POST("upload")
public Call<notificationVO>notifyAttachment(#Query("token")String token,
#Part MultipartBody.Part attachFile); // #Part MultipartBody.Part file
Implementation
public notificationVO notifyAttachment(String token,MultipartBody.Part fileUri,final Context context){
WebservicesApi mRestAPIWService = ApiUtilsForWS.getAPIService(context,);
Call<notificationVO> call = mRestAPIWService.notifyAttachment(token,fileUri);
try {
Response<notificationVO> response = call.execute();
if(response.isSuccessful())
{
Log.e(TAG,"Success."+response.code());
return response.body();
}
else
{
Log.e(TAG,"Failed."+response.code());
return null;
}
} catch (IOException e1) {
e1.printStackTrace();
return null;
}
}
Use interface like this below, remove #Query annotation add as #Part in your interface.
interface Service {
#Multipart
#POST("upload")
Call<notificationVO> postImage(#Part MultipartBody.Part image, #Part("token") RequestBody name);
}
Check your File path is valid and also check the file size to confirm that you are getting file properly from your file picker.
File origFile = new File(PathHolder);
int file_size = Integer.parseInt(String.valueOf(origFile .length()/1024));
If everything is OK then try this below option to upload your file it will work
RequestBody mFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", file.getName(), mFile);
RequestBody token = RequestBody.create(MediaType.parse("text/plain"), file.getName());
// Service is interface name you can use your own interface name
Service uploadImage = retrofit.create(Service.class);
Call<notificationVO> fileUpload = uploadImage.postImage(fileToUpload, token);
fileUpload.enqueue(new Callback<notificationVO>() {
#Override
public void onResponse(Call<notificationVO> call, Response<notificationVO> response) {
}
#Override
public void onFailure(Call<notificationVO> call, Throwable t) {
}
});
This is the code im using for multiple uploads to server.This format is working fine in POSTMAN and not working in by using retrofit2. Can anybody help me
#Multipart
#POST("/api/answers/save")
Call<ResponseBody> upload(#Header("Authorization") String
authorization,#Part("input_answer") RequestBody answer_string,#Part
List<MultipartBody.Part> files);
check this
#NonNull
private RequestBody createPartFromJsonString(String json_answers_string) {
return RequestBody.create(
okhttp3.MultipartBody.FORM, json_answers_string);
}
check this , using this for converting file to multipart body
#NonNull
private MultipartBody.Part prepareFilePart(String attachment_name, String absolute_path) {
File file = new File(absolute_path);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
return MultipartBody.Part.createFormData(attachment_name, file.getName(), requestFile);
}
This is used for multiple uploads
private void multipartUploadAudit(JSONObject json_object, List<String> FileNameWithAbsolutePath) {
progressBar.setVisibility(View.VISIBLE);
//convert jsonobject to string
Gson gson = new Gson();
String answers_string_json_obj = gson.toJson(json_object);
APIService mAPIService = ApiUtils.getAPIService();
List<MultipartBody.Part> parts = new ArrayList<>();
// add dynamic
for (int i = 0; i < FileNameWithAbsolutePath.size(); i++) {
String name = FileNameWithAbsolutePath.get(i).substring(FileNameWithAbsolutePath.get(i).lastIndexOf("/") + 1);
String names[] = name.split("\\.");
parts.add(prepareFilePart(names[0], FileNameWithAbsolutePath.get(i)));
}
// add another part within the multipart request
RequestBody answer_string = createPartFromJsonString(answers_string_json_obj);
// finally, execute the request
Call<ResponseBody> call = mAPIService.upload("Bearer " + sharedPrefUserData.getUserData().getAuthToken(), answer_string, parts);
// Call<ResponseBody> call = mAPIService.upload( description, parts);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
progressBar.setVisibility(View.GONE);
if (response.isSuccessful()) {
response.body(); // do something with that
Toast.makeText(AuditQuestionsLandingScreen.this, response.body().toString(), Toast.LENGTH_SHORT).show();
} else {
response.errorBody(); // do something with that
Toast.makeText(AuditQuestionsLandingScreen.this, response.errorBody().toString(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progressBar.setVisibility(View.GONE);
internetConnectionChecker.serverErrorAlert();
Log.v("Upload_error:", t.getMessage());
Toast.makeText(AuditQuestionsLandingScreen.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
After long struggle i got my answer. i made a mistake by converting jsonobject to string by using gson. it added enveloped my string with
{"nameValuePairs": {}}
so i used this.
RequestBody.create(MediaType.parse("multipart/form-
data"),String.valueOf(json_object))
Interface:
#Multipart
#POST("emp/passportupload")
Single<ApiResponse> uploadPassportImage(#Query("passportnumber") String passportNumber, #Part MultipartBody.Part file);
Calling api:
File file = new File(model.getImage().getPath());
if (!file.exists()) return null;
RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part filePart = MultipartBody.Part.createFormData(ApiConstant.PICTURE_UPLOAD_PARAM, file.getName(), requestBody);
dataService.uploadPassportImage(map, filePart)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
I am using this method to upload image to the server but server can't validate it as an image, hence giving me a response like
"Provided File Is Not A Valid Picture. Please Provide A PNG/JPG File"
But, I have uploaded the same image file through postman and it was successful. Here is the request: (N.B: passportnumber is a params, not a form data)
#Multipart
#POST("changeCompanyLogo")
Call<ChangeLogoResponse> changeCompanyLogo(#Part MultipartBody.Part image, #Part("JSON") RequestBody name);
In service write this code
ChangeLogoAPI service = ServiceHandler.getClient().create(ChangeLogoAPI.class);
File file = new File(intent.getStringExtra("imagePath"));
RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("companyLogo", file.getName(), reqFile);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), new Gson().toJson(new ChangeLogoParams()));
Call<ChangeLogoResponse> call = service.changeCompanyLogo(body, name);
call.enqueue(new Callback<ChangeLogoResponse>() {
#Override
public void onResponse(Call<ChangeLogoResponse> call, Response<ChangeLogoResponse> response) {
Log.d(TAG, "response: " + response.isSuccessful());
}
#Override
public void onFailure(Call<ChangeLogoResponse> call, Throwable t) {
}
});
#POST("{path}")
Call<Void> uploadFile(#Header("Content-Type") String type, #Body RequestBody photo, #Path("path") String path);
File file = new File("YOUR_FILE_URI");
String filename = file.getName();
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
final String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
InputStream in = null;
RequestBody requestBody = null;
try {
in = new FileInputStream(file);
byte[] buf;
buf = new byte[in.available()];
while (in.read(buf) != -1);
requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), buf);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ApiConfig getResponse = AppConfig.getRetrofit().create(ApiConfig.class);
Call<Void> call = getResponse.uploadFile(type, requestBody , posturl);
U can try like this u need to set map parameter as a multipart look at the below example here I am passing both userId and image
RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
MultipartBody.Part id = MultipartBody.Part.createFormData("userId", userId);
Call<ProfilePicUpdateResponse> call = apiService.updateProfilePic(id,fileToUpload);
use this awesome library : [Easily upload files (FTP / Multipart / Binary) in the background with progress indication notification] https://github.com/gotev/android-upload-service/wiki/Setup it will do the rest of work for you.
private void Dialog_profile_pic() {
// create upload service client
File file = new File(selectedImagePath);
// 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("memFile", file.getName(), requestFile);
// add another part within the multipart request
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), ApiResultCode.getApiKey());
RequestBody description2 =
RequestBody.create(
MediaType.parse("multipart/form-data"), ApiResultCode.getApiType());
Call<LoginPicture> loginPictureCall = RequestClient.getInstance()
.loginPicture(description, description2, body);
loginPictureCall.enqueue(new Callback<LoginPicture>() {
#Override
public void onResponse(Call<LoginPicture> call, Response<LoginPicture> response) {
//CONNECTION SUCCESS
LoginPicture NewUser = response.body();
if (NewUser.getResponsedata().getResultCode() == 100) {
Log.e("DEBUG", "CONNECTION result: CONGRATS");
} else {
Log.e("DEBUG", "CONNECTION result: " + NewUser.getResponsedata().getResultCode() + NewUser.getResponsedata().getResultMessage());
}
}
#Override
public void onFailure(Call<LoginPicture> call, Throwable t) {
//CONNECTION FAIL
Log.e("DEBUG", "CONNECTION result: FAIL" );
}
});
}
\
public interface ApiInterface {
#Multipart
#POST("/memberController/joinUploadProfile.json")
Call<LoginPicture> loginPicture(#Part("apiKey") RequestBody apiKey, #Part("apiType") RequestBody apiType, #Part("memFile") MultipartBody.Part file); //multi part
\
I am trying to pass in two string parameters and an image file using retrofit2 but I am failing to get a connection. Anyone can help me find what I need to do? I have been struggling over this for 2 days now.
//In Request Client API Interface
#Multipart
#POST("URL.json")
Call<LoginPicture> loginPicture(#PartMap() Map<String, RequestBody> mapPhoto); //multi part
//In activity
private void Dialog_profile_pic(final Uri selectedImageUri) {
// create upload service client
File file = new File(selectedImagePath);
HashMap<String, RequestBody> map = new HashMap<>();
RequestBody description =
RequestBody.create(
MediaType.parse("text/plain"),"content1");
RequestBody description2 =
RequestBody.create(
MediaType.parse("text/plain"), "content2");
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(MediaType.parse("image/jpeg"), file);
map.put("memFile\"; filename=\""+file.getName(),requestFile);
map.put("apiKey",description);
map.put("apiType", description2);
Call<LoginPicture> loginPictureCall = RequestClient.getInstance()
.loginPicture(map);
loginPictureCall.enqueue(new Callback<LoginPicture>() {
#Override
public void onResponse(Call<LoginPicture> call, Response<LoginPicture> response) {
Picasso.with(Activity_create.this).load(NewUser.getResponsedata().getResultObject()).into(iv_profile_pic);
} else {
Log.e("DEBUG", "CONNECTION result: " + NewUser.getResponsedata().getResultCode() + NewUser.getResponsedata().getResultMessage());
}
}
#Override
public void onFailure(Call<LoginPicture> call, Throwable t) {
//통신 실패 시
Log.e("DEBUG", "CONNECTION result: FAIL");
}
});
}
//And it works now