How to upload a file from Android to Java Web Service? - java

I'm trying to send a file from android to my webserver through a Rest API, but I don't know how to handle the MultipartBody.Part object in java.
API Request:
#Multipart
#POST("utilizadores/upload")
Call<ResponseBody> uploadPhoto(
#Part MultipartBody.Part fotografia);
Android Code:
File file = new File(getPath(data));
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part parts = MultipartBody.Part.createFormData("images", file.getName(), requestBody);
Call<ResponseBody> call = RetrofitClient
.getInstance()
.getApi()
.uploadPhoto(parts);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(getContext(), response.message(), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
Java Code:
What should I pass as parameter in the next function 'uploadFile()'?
The value of fotografia is '(NULL)'.
#POST
#Path("/upload")
#Produces(MediaType.APPLICATION_JSON)
public Response uploadFile(#QueryParam("fotografia") String fotografia) {
BD bd = new BD();
int id = 54;
try {
String path = "/fotografias/" + id + ".jpg";
//guardarFicheiro(fotografia, path);
ConnectionBD connection = bd.abrirLigacao();
PreparedStatement ps = connection.getConn()
.prepareStatement("UPDATE utilizador SET fotografia=? WHERE id=?");
ps.setString(1, fotografia);
ps.setInt(2, id);
int x = ps.executeUpdate();
if (x > 0) {
bd.fecharConexao(connection);
return Response.ok().build();
}
bd.fecharConexao(connection);
} catch (SQLException ex) {
System.out.println(ex);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}

Related

Need to get a string from response returned by api using retrofit2

I am trying to get string value returned by API on success. I am getting success but I do not getting the required value in the response, but when I navigate to response-> body-> responseBody then it shows me that value but I am unable to get that value (please check screen shot for detail).
private void uploadImage(String imagePath) {
try{
showProgressDialogue();
File file = new File(imagePath);
RequestBody photoContent = RequestBody.create(MediaType.parse("multipart/form data"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("file",file.getName(),photoContent);
//RequestBody description = RequestBody.create(MediaType.parse("description"),"abc");
UploadService uploadService = APIClient.getClient().create(UploadService.class);
Call call1 = uploadService.UploadOMRExamPaper(photo);
call1.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
progressBar.dismiss();
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
progressBar.dismiss();
Toast.makeText(getApplicationContext(), t.getMessage(),Toast.LENGTH_LONG).show();
}
});
}catch (Exception e){
progressBar.dismiss();
Toast.makeText(this, e.getMessage(),Toast.LENGTH_LONG).show();
}
}
Change your code:
From:
File file = new File(imagePath);
RequestBody photoContent = RequestBody.create(MediaType.parse("multipart/form data"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("file",file.getName(),photoContent);
To:
File file = new File(imagePath);
RequestBody photoContent = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("upload", file.getName(), photoContent );
Note:"upload" is just example here,you should write there from your api paramater.

Why the String inside Controller not printing anything?

I am trying to send Image and Id using retrofit for that i am sending Multipart file and String.
This is my Upload Method on Android side ->
private void UploadFiles() {
File uploadFile = fileArrayList.get(0);
if (uploadFile != null) {
Log.d(TAG, "UploadFiles: File Name is -> " + uploadFile.getName());
// Parsing any Media type file
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), uploadFile);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part cropImage = MultipartBody.Part.createFormData("cropImage", uploadFile.getName(), requestFile);
RequestBody cropId = RequestBody.create(MediaType.parse("multipart/form-data"), uploadFile.getParentFile().getName());
Api.uploadCropImage(cropImage,cropId, new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.body() != null) {
Log.d(TAG, "onResponse: Success" + response.body().getResponse());
}
else{
Log.d(TAG, "onResponse: null Response");
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.d(TAG, "onResponse: Failure");
}
});
}
}
My Upload CropImage Method ->
public static void uploadCropImage(MultipartBody.Part multipartBody,RequestBody cropId,
Callback<BasicResponse> callback) {
UploadCropImageApi uploadCropImageApi = retrofit.create(UploadCropImageApi.class);
Call<BasicResponse> call = uploadCropImageApi.uploadCropImage(multipartBody,cropId);
call.enqueue(callback);
}
My Interface ->
public interface UploadCropImageApi {
#Multipart
#POST(UPLOAD_FILE_TO_AWS_URL)
Call<BasicResponse> uploadCropImage(#Part MultipartBody.Part cropImage, #Part("cropId") RequestBody cropId);
}
This is my Spring Controller, What's wrong with it? It's not printing cropId.
#RequestMapping(value = "/UploadCropImage", method = RequestMethod.POST, consumes = {"multipart/form-data"})
#ResponseBody
public String UploadImage(#RequestBody MultipartFile cropImage,#RequestBody String cropId ,HttpServletRequest request) {
System.out.println("String is -> " + cropId);
return null;
}
You cannot use two #RequestBody as it can bind to a single object only (the body can be consumed only once)
You need to use #RequestParam String cropId instead of RequestBody.
See here for clarification
UPDATE :Here is your controller method look like
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<GenericResponseVO<? extends IServiceVO>> uploadFileHandler(#RequestParam("name") String name, #RequestParam("file") MultipartFile file,HttpServletRequest request, HttpServletResponse response) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// Creating the directory to store file
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists())
dir.mkdirs();
// Create the file on server
File serverFile = new File(dir.getAbsolutePath() + File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
System.out.println("Server File Location=" + serverFile.getAbsolutePath());
return null;
} catch (Exception e) {
return null;
}
}
}

retrofit2 for multipart file upload working in one class but not multiple class

I am using retrofit2 for multi part file upload. But when I use the below code in two forms, I get an error. I am using the code to upload profile creation and update after login. If I use this only in update profile or register page it's working fine.
My code [Client + Interface + Main class]:
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface FileUploadService {
#Multipart
#POST("ProfileFileUpload")
Call<ResponseBody> uploadFile(
#Part("authToken") RequestBody authToken,
#Part MultipartBody.Part docFile,
#Part("FileName") RequestBody FileName,
#Part("TypeName") RequestBody TypeName);
}
private void executeMultipartPost(String picturePath){
try {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofitProfile = new Retrofit.Builder()
.baseUrl("url")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
mFileUploadService = retrofitProfile.create(FileUploadService.class);
File file = new File(Environment.getExternalStorageDirectory(),picturePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("docFile", file.getName(), requestFile);
RequestBody autoToken = RequestBody.create(MediaType.parse("text/plain"), "xxxxxxxxxx");
RequestBody FileName = RequestBody.create(MediaType.parse("text/plain"), file.getName());
RequestBody FileType = RequestBody.create(MediaType.parse("text/plain"), "image");
Call<ResponseBody> req = mFileUploadService.uploadFile(autoToken, body,FileName,FileType);
req.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
if (response.isSuccessful()) {
String Response="";
// dont work
String objRes = response.body().string();
JSONObject jsonObject = new JSONObject(objRes);
profileImage = jsonObject.optString("response").toString();
Response = jsonObject.optString("status").toString();
dialog.dialogBoxWithAlert(ActivityCreateAccount.this,"Alert", Response);
} else {
// works on failure
dialog.dialogBoxWithAlert(ActivityCreateAccount.this,"Error", "There is a error");
}
} catch (Exception e) {
e.printStackTrace();
}
progDailog.dismiss();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progDailog.dismiss();
t.printStackTrace();
}
});
} catch (Exception e) {
// handle exception here
Log.e(e.getClass().getName(), e.getMessage());
}
}
Crashlog
03-13 22:32:33.447 23389-23389/com.source.websys.rwm A/art: art/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc:2077] Check failed: instr_code == Instruction::INVOKE_INTERFACE || instr_code == Instruction::INVOKE_INTERFACE_RANGE Unexpected call into interface trampoline: invoke-virtual {v1, v127, v2646493288, v85, v48}, thing#13744

Uploading image by using Retrofit

I've been trying to upload an image from my application through API. But I keep getting this as response:
{"error":"<p>You did not select a file to upload.<\/p>"}
This is my code:
APIService.java
#Multipart
#POST("/media/upload.html")
Call<UploadImg> uploadimage (#Part MultipartBody.Part file);
UploadImageActivity.java
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null && data.getData() != null){
Uri uri = data.getData();
Picasso.with(this).load(uri).fit().into(btn_img_picker);
String imagePath;
if (data.toString().contains("content:")) {
imagePath = getRealPathFromURI(uri);
} else if (data.toString().contains("file:")) {
imagePath = uri.getPath();
} else {
imagePath = null;
}
File file = new File(imagePath);
System.out.println(imagePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("userfile", file.getName(), requestFile);
System.out.println(file.getName());
Call<UploadImg> call = mAPIService.uploadimage(body);
call.enqueue(new Callback<UploadImg>() {
#Override
public void onResponse(Call<UploadImg> call, Response<UploadImg> response) {
System.out.println(response.raw());
}
#Override
public void onFailure(Call<UploadImg> call, Throwable t) {
System.out.println(t);
}
});
}
}
public String getRealPathFromURI(Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = getContentResolver().query(contentUri, proj, null, null,
null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
I have tested sending image in Postman's form-data. I can send a picture from my desktop and received intended response. But I can't do the same with my code in android.
Am I sending the incorrect path format of the image? Currently, variable imagePath has an output like this:
/storage/emulated/0/Download/download.jpg
If this is the incorrect path to send, please tell the correct one. Thanks in advance.
try this
#Multipart #POST("user/updateprofile") Observable<ResponseBody>
updateProfile(#Part("user_id") RequestBody id, #Part("full_name")
RequestBody fullName, #Part MultipartBody.Part image, #Part("other")
RequestBody other);
pass it like this
File file = new File("/storage/emulated/0/Download/Corrections 6.jpg"); 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("image", file.getName(), requestFile);
add another part within the multipart request
RequestBody fullName = RequestBody.create( MediaType.parse("multipart/form-data"), "Your Name");
service.updateProfile(id, fullName, body, other)
You can use below code for uploading image
First you write code for calling request
//profile pic is image path
RequestBody imagePath = Utility.imageToBody(profilePic);
TestApiInterface service = WebServiceCaller.getClient();
Call<SuccessResponse> call = service.mediaUpload(imagePath);
call.enqueue(new Callback<SuccessResponse>() {
#Override
public void onResponse(Call<SuccessResponse> call,
Response<SuccessResponse> response) {
SuccessResponse result;
if (response.isSuccessful()) {
result = response.body();
}
}
#Override
public void onFailure(Call<SuccessResponse> call, Throwable t) {
}
});
Then you write code for API
#Multipart
#POST("user/mediaupload")
Call<SuccessResponse> mediaUpload(#Part("media_file\"; filename=\"test_media.png\" ") RequestBody media_file);
Then code for Imagetobody covert is below
public static RequestBody imageToBody(String text) {
RequestBody requestBody;
if (text != null && text.length() > 0) {
MediaType MEDIA_TYPE = MediaType.parse("image/*");
File file = new File(text);
requestBody = RequestBody.create(MEDIA_TYPE, file);
} else {
requestBody = null;
}
return requestBody;
}
Try this I had another way to implement
Inside your interface
#Multipart
#POST("edit_profile")
Call<TokenResponse> getTokenAccess(#PartMap Map<String, RequestBody> map);
Call in your Activity
private void getData() {
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("your_base_url_here")
.addConverterFactory(GsonConverterFactory.create())
.build();
Click service=retrofit.create(Click.class);
File file = new File("/storage/sdcard0/Pictures/OGQ/Puskinn Sharma_Jump roof skyscraper_YkRiRWpYcw.jpg");
//make sure your image path is valid
String convert_File_2String= String.valueOf(file);
String fileNAme=convert_File_2String.substring(convert_File_2String.lastIndexOf("/")+1);
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "Sunil");
RequestBody id = RequestBody.create(MediaType.parse("text/plain"), "56");
RequestBody lastname= RequestBody.create(MediaType.parse("text/plain"), "Kumar");
Map<String, RequestBody> map = new HashMap<>();
map.put("profile_pic\"; filename=\""+fileNAme+"\" ", fbody);
map.put("firstname", name);
map.put("user_id", id);
map.put("lastname",lastname);
Call<TokenResponse> tokenResponseCall=service.getTokenAccess(map);
tokenResponseCall.enqueue(new Callback<TokenResponse>() {
#Override
public void onResponse(Call<TokenResponse> call, Response<TokenResponse> response) {
TokenResponse tokenResponse=response.body();
Log.e("93","MA>>"+tokenResponse.getJwt());
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<TokenResponse> call, Throwable throwable) {
Log.e("172","><<>>"+throwable);
Log.e("TAG", "onFailure: 173"+call.toString() );
}
});
}

How to use Retrofit in Android POST method along with body?

I have one url with request parameter is in JsonFormat like
{"EmailAddress":"user#gmail.com","PassWord":"password"} it's requested parameter.
When i used in POSTMAN then its okey.but when i request with program then that time i got error response. ihave tried till like this please see this snippet.
public class LoginModel {
#SerializedName("EmailAddress")
public String userName;
#SerializedName("PassWord")
public String userPass;
}
#Override
public String toString() {
Log.e("POSTLOGIN_MODEL" , userName+"||"+userPass);
return "{" +
"EmailAddress='" + userName + '\'' +
", PassWord='" + userPass + '\'' +
'}';
}
}
After that i used Interface.
public interface ApiService {
#FormUrlEncoded
#POST("/json/syncreply/AuthenticateUserRequest?")
Call<LoginResponse> LoginService(#Field("EmailAddress") String userName, #Field("PassWord") String userPass, Callback<LoginResponse> callBack);
After that i used to call this interface method through activity.
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(input_username.getText().toString() != null && input_password.getText().toString() != null
&& !input_username.getText().toString().isEmpty() && !input_password.getText().toString().isEmpty()){
LoginModel loginCredentials = new LoginModel();
loginCredentials.userName = "test#gmail.com";
loginCredentials.userPass = "password";
String request = "{\"EmailAddress\":\"raj#gmail.com\"," +
"\"PassWord\":\"pass\"}";
sendPost(loginCredentials);
}else{
Toast.makeText(getApplicationContext() , "Please enter valid Username and Password." , Toast.LENGTH_LONG).show();
}
}
});
public void sendPost(LoginModel name) {
Log.e("TAG","||"+name.userPass+"||"+name.userName);
// mAPIService.savePost(name).enqueue(new Callback<LoginModel>() {
Call<LoginResponse> call = mAPIService.LoginService(name.userName, name.userPass, new Callback<LoginResponse>() {
#Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
Log.e("TAG" , "RESPONSE"+"||"+response.body());
}
#Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
Log.e("TAG" , "FAILURE"+"||"+t.getMessage());
}
});
}
Thanks In Advance.any answer will appriciated.my english is please avoid it.
Hey Rajan use Request body to pass Json
String request = "{\"EmailAddress\":\"raj#gmail.com\"," + "\"PassWord\":\"pass\"}";
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),request);
#Headers("Content-Type: application/json; charset=utf-8")
#POST("/json/syncreply/AuthenticateUserRequest")
Call<ResponseBody> AuthenticateUserRequest(#Body RequestBody body);
aCall.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
First on your rest client interface side change the method like below, instead of taking email and password both seperately take only one ArrayList of String there :
#FormUrlEncoded
#POST(WEBSERVICE_NAME)
Call<ModelClass> methodName(
#Field("parameters" + "[]") ArrayList<String> paramsArrayList
);
Now, convert your arraylist of model class in to JSON string using GSON library like this,
private ArrayList<String> getModelClassArrayinString(ArrayList<ModelClass> arrayList) {
ArrayList<String> arrayListString = new ArrayList<>();
for (int i = 0; i < arrayList.size(); i++) {
arrayListString.add(new Gson().toJson(arrayList.get(i)).toString());
}
return arrayListString;
}
So your final call will be like this :
Call<LoginResponse> call = mAPIService.LoginService(getModelClassArrayinString(arrayListofModelClass), new Callback<LoginResponse>() {
#Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
Log.e("TAG" , "RESPONSE"+"||"+response.body());
}
#Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
Log.e("TAG" , "FAILURE"+"||"+t.getMessage());
}
});

Categories