I am using retrofit 2 library to send image from android device to a server which runs on Spring - Boot.
I want to simply send an image to see, if all is ok, so i perform this simple type of request:
On server side my controller looks like this:
#PostMapping(value = "/updatePhoto" )
public String updateUserPhoto(#RequestPart(name = "img") MultipartFile img) {
{
System.out.println("Request update photo "+ img.getOriginalFilename());
return "OK";
}
This is my request
#POST("/updatePhoto")
#Multipart
Call<String> updateUserPhoto(#Part MultipartBody.Part img);
This is how i perform it:
File file = new File(mediaPath);
RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
System.err.println(filename+" " + fileToUpload);
MainAplication.getServerRequests().updateUserPhoto(fileToUpload)
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.body()!=null){
System.err.println(response.body());
}else{
System.err.println("RESPONSE BODY NULL");
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
System.err.println("UPDATE PHOTO FAIL " +t.getMessage());
}
});
But every time i try to send an image, my server throws an exception :
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'img' is not present
And cant understand where im doing wrong, i had tried a lot, but a can`t solve this problem. Any ideas what must i improve ?
Try this "img" instead of "file"
RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("img", file.getName(), requestBody);
Related
I have to upload video file to Server using API, I am using Retrofit. I tried Multipart (by using different approaches) but failed.
I have to upload a video file, reference key as a string and url as a string (in body). In header, I have to upload token.
First I tried this:
Interace:
#Multipart
#POST(url)
Call<LivenessRequest> requestFun(#Header("Authorization") String token,
#Part("reference") RequestBody referenceId,
#Part("url") RequestBody url,
#Part("file") RequestBody videoFile);
Making RequestBody Objects:
RequestBody fileBody;
RequestBody referenceBody;
RequestBody urlBody;
fileBody = RequestBody.create(okhttp3.MediaType.parse("video/*"), videoFile);
referenceBody = RequestBody.create(okhttp3.MediaType.parse("text/plain"), String.valueOf(
"refernce_id_here"));
urlBody = RequestBody.create(okhttp3.MediaType.parse("text/plain"), String.valueOf(
"www.google.com"));
calling API:
interface().requestFun(token,
referenceBody, urlBody, videoFileBody).enqueue(new retrofit2.Callback<request>() {
#Override
public void onResponse(retrofit2.Call<request> call, Response<request> response) {
}
#Override
public void onFailure(retrofit2.Call<request> call, Throwable t) {
}
});
I tried it with another approach that is:
Interface:
#Multipart
#POST(url)
Call<LivenessRequest> requestFun(#Header("Authorization") String token,
#Body RequestBody body);
Making RequestBody Object:
RequestBody body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file",videoFile.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), videoFile))
.addFormDataPart("url","www.google.com")
.addFormDataPart("reference", reference)
.build();
API calling:
interface().requestFun(token, body).enqueue(new retrofit2.Callback<request>() {
#Override
public void onResponse(retrofit2.Call<request> call, Response<request> response) {
}
#Override
public void onFailure(retrofit2.Call<request> call, Throwable t) {
}
});
Postman Screenshot of this api is attached:
enter image description here
I'm new the Android developer, I'm working on an application, I have activity is users can upload their items to the server (the text and image), but the problem is upload text is easy , I used Volley to upload the text to server, but I struggle long time to upload the multiple the images to server. I saw the Retrofit 2 really good for multiple file upload but I have A lot problems.
I tried a lot but to no avail and I tried to share one of the codes with you so you can help me.
I also use bearer tokens but I don't know it is correct or not.
File file1 = new File(patch_img1);
File file2 = new File(patch_img2);
File file3 = new File(patch_img3);
RequestBody image1 = RequestBody.create(MediaType.parse("image/*"),
file1);
RequestBody image2 = RequestBody.create(MediaType.parse("image/*"),
file2);
RequestBody image3 = RequestBody.create(MediaType.parse("image/*"),
file3);
RequestBody invoice = RequestBody.create(MediaType.parse("text/plain"), invoices);
UserSharedPref sharedPref = new UserSharedPref(CompletedServiceActivity.this);
WebServicesAPI request = APIClient.getApiClient("https://text.com/api/").create(WebServicesAPI.class);
Call<ResponseBody> call = request.upload(sharedPref.getUserToken(),image1,image2,image3,invoice);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
my interface.class
#POST("invoices")
Call<ResponseBody> upload(
#Header("Authorization") String authorization,
#Part("image1") RequestBody image1,
#Part("image2") RequestBody image2,
#Part("image3") RequestBody image3,
#Part("invoice") RequestBody invoice
);
APIClient.class
public class APIClient {
public static Retrofit retrofit = null;
public static Retrofit getApiClient(String url) {
if (retrofit == null) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
retrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
Try this it's work with me :
String path3 = image3.getPath();
File file3 = new File(path3);
// Parsing any Media type file
RequestBody requestBody3 = RequestBody.create(MediaType.parse("*/*"), file3);
MultipartBody.Part fileToUpload3 = MultipartBody.Part.createFormData("filename", file3.getName(), requestBody3);
RequestBody filename3 = RequestBody.create(MediaType.parse("text/plain"), image3.getName());
Calling method:
UploadImage3(fileToUpload3,filename3);
Interface:
#POST("uploadimage3.php")
#Multipart()
Observable<ApiResponse>UploadImage3(#Part MultipartBody.Part file, #Part("filename") RequestBody name);
I am trying to post some multipart form data via Retrofit in Android to a web service.
The web services's API expects the following parameters to be passed as field of a multipart form data:
Name Type
company_id text/plain
image image/*
It also expects an authorization token to be passed as a query string parameter.
So i have defined my API interface call like this:
#Multipart
#POST("/companies/uploadImage")
#Headers({
"Content-Type: multipart/form-data",
"Accept: application/json"
})
Call<ServerResponse> companyUploadImage( #Part("company_id") RequestBody companyId, #Part MultipartBody.Part file, #Query("token") String token);
Afterwards this is how i call the above API interface method in a custom class:
RequestBody companyId = RequestBody.create(MediaType.parse("text/plain"), LocalStorage.getInstance().getCompanyId());
File file = new File(postPath);
MultipartBody.Part image = MultipartBody.Part.createFormData("image", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
Call<ServerResponse> uploadProfileImage = router.companyUploadImage(companyId, image, token);
uploadProfileImage.enqueue(new Callback<ServerResponse>() {
#Override
public void onResponse(Call<ServerResponse> call, Response<ServerResponse> response) {
Log.e("Upload Profile Image: ", response.body().getMessage());
}
#Override
public void onFailure(Call<ServerResponse> call, Throwable t) {
Log.e("Upload Profile Image Error: ", t.getMessage());
}
});
The request is sent successfully to the server, so no networking exceptions occur, however the multipart form values, company_id and image, are received empty on the server side
Any idea?
Thank you!
I managed to solve the issue. It seems that the solution was as simple as removing the #Header annotation from the API interface method. So now it looks like this:
#Multipart
#POST("/companies/uploadImage")
Call<ServerResponse> companyUploadImage( #Part("company_id") RequestBody companyId, #Part MultipartBody.Part file, #Query("token") String token);
Maybe someone will find this post helpful.
i'm using retrofit2 library for post data to server, I need to upload a file or photo with POST request and get it's response. So i have two ways:
Encoding the file to base64 and sending it as a text in post body.
Using Multi part request and sending the file directly .
And i tried them, but in both ways, i have same problem:
when I send small files (for example under 500 bytes),I get successful result.
But the problem occurs when i send a large file. I get nothing until the timeout finishes, in AVD I get successful response (Also in Postman), but in real devices (HTC with android 5.1 & Samsung S6 with Android 7.0) the below error occurs:
java.io.IOException: unexpected end of stream on Connection{myIp:port, proxy=DIRECT# hostAddress=/myIp:port cipherSuite=none protocol=http/1.1
Call Method:
#Multipart
#POST("uploaddata")
Call<ResponseBody> uploaddate(#Part("file") RequestBody filePart, #Part("token") RequestBody token,
#Part("type") RequestBody type, #Part("name")RequestBody name);
Main method:
public void uploadImage(String type, File file, String name, String token, final DataInterface listener) {
RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody tokenPart = RequestBody.create(MediaType.parse("text/plain"), token);
RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"), name);
RequestBody typePart = RequestBody.create(MediaType.parse("text/plain"), type);
Call<ResponseBody> uploadData = apiInterface.uploaddate(filePart, tokenPart, typePart, namePart);
uploadData.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
listener.onResponseListener(response.body());
} else {
Log.e(TAG, "uploadData -----> response.isSuccessful == false");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "uploadData onFailure -----> " + t);
}
});
}
Can you post the log output of your error
Did it return anything like a large binary data ??
Try this:
#Multipart
#POST("uploaddata")
Call<ResponseBody> uploaddate(#Part MultiPart.Body filePart,
#Part("token") RequestBody token,
#Part("type") RequestBody type,
#Part("name")RequestBody name);
Main method:
public void uploadImage(String type, File file, String name, String token,
final DataInterface listener) {
RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), file);
MultiPartBody.Part body = MultiPartBody.Part.createFormData("filePart",file.getName(),filePart);
RequestBody tokenPart = RequestBody.create(MediaType.parse("text/plain"), token);
RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"), name);
RequestBody typePart = RequestBody.create(MediaType.parse("text/plain"), type);
Call<ResponseBody> uploadData = apiInterface.uploaddate(body, tokenPart, typePart, namePart);
uploadData.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
listener.onResponseListener(response.body());
} else {
Log.e(TAG, "uploadData -----> response.isSuccessful == false");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "uploadData onFailure -----> " + t);
}
});
}
I have to capture image and upload it to server using retrofit2
My API
#Multipart
#POST("photo/")
Call<NetWorkResponse<String>> uploadPhoto(#Header("Authorization") String token,
#Part("category") String category,
#Part MultipartBody.Part photo);
My method to upload photo
public static void uploadPhoto(String nfToken, String category, File photoFile) {
RequestBody filePart = RequestBody.create(MediaType.parse("image/jpeg"), photoFile);
MultipartBody.Part file = MultipartBody.Part.createFormData("photo", photoFile.getName(), filePart);
Call<NetWorkResponse<String>> call = nfApi.uploadPhoto(nfToken, category, file);
call.enqueue(new Callback<NetWorkResponse<String>>() {
#Override
public void onResponse(Call<NFNetWorkResponse<String>> call, Response<NetWorkResponse<String>> response) {
if (response.isSuccessful()) {
NetWorkResponse<String> netWorkResponse = response.body();
} else {
}
}
#Override
public void onFailure(Call<NetWorkResponse<String>> call, Throwable t) {
}
});
}
My photo file Uri: file:///storage/emulated/0/Pictures/Food/IMG_20170731_094856_2128319239.jpg
When I upload the file to server, I got error Bad Request, code 400. which may indicate that my param is wrong but I am quite sure there is nothing wrong with that. I guess sth is wrong with the picture, sth is wrong with MediaType.parse("image/jpeg")
Instead that should be:
File f = new File(mCurrentPhotoPath);
Uri pictureUri = Uri.fromFile(f);
String contentType = getContentResolver().getType(pictureUri);
MediaType.parse(contentType)
But the problem is that the Uri path is file:// not content:// so contentType is null
Any idea what's wrong when I upload photo to the server
Instead of Photo file URL file:///storage/emulated/0/Pictures/Food/IMG_20170731_094856_2128319239.jpg
Pass this one /storage/emulated/0/Pictures/Food/IMG_20170731_094856_2128319239.jpg