Related
I'm trying to upload an image to the server using retrofit 2 multipart request and Gson parser
I tested the api by postman and its working fine but in android I'm getting the mentioned exception
Here's my code
this is retrofit dependency
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
Api Client
public class ApiClient {
public static final String BASE_URL = "http://www.AAbd.com/api/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
Gson gson = new GsonBuilder()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
Api Interface
#POST("edit/Image")
#Multipart
Call<AuthModel> addImage (#Part("api_token") RequestBody api_token,
#Part("image") MultipartBody.Part image);
Model
#Expose
#SerializedName("api_token_status")
private String api_token_status;
#Expose
#SerializedName("status")
private String status;
#Expose
#SerializedName("message")
private String message;
public String getMessage() {
return message;
}
public String getApi_token_status() {
return api_token_status;
}
public String getStatus() {
return status;
}
Calling the request
public void addImageRequest (Bitmap image) {
try {
File f = new File(getCacheDir(), "offf");
f.createNewFile();
Bitmap bitmap = image;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = new FileOutputStream(f);
fos.write(bitmapdata);
fos.flush();
fos.close();
RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), f);
MultipartBody.Part body = MultipartBody.Part.createFormData("image", f.getName(), reqFile);
RequestBody tokenRequest = RequestBody.create(MediaType.parse("text/plain"), token2);
apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<AuthModel> call = apiInterface.addImage(tokenRequest, body);
call.enqueue(new Callback<AuthModel>() {
#Override
public void onResponse(Call<AuthModel> call, Response<AuthModel> response) {
AuthModel result = response.body();
if(result != null) {
String status = result.getStatus();
String msg = result.getMessage();
if(status.equals("true")) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
Log.e("errorIs", msg);
} else {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
Log.e("errorIs", msg);
}
} else {
try {
//Toast.makeText(context, response.errorBody().string() , Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<AuthModel> call, Throwable t) {
Toast.makeText(MainActivity.this, t.toString(), Toast.LENGTH_LONG).show();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I checked all the previous questions regarding this issue but I didn't find a possible solution for my case. Please help and thanks in advance
I am new to android .
I want to upload image as form data using Retrofit Post method.
I am using com.squareup.retrofit2:retrofit:2.3.0
This is my request body.
**Make interface like this add "MultipartBody.Part" in request and set your image path as post method and you can upload image using retrofit use this networkclient class to create retrofit instance **
public class NetworkClient {
private static final String BASE_URL = "";
private static Retrofit retrofit;
public static Retrofit getRetrofitClient(Context context) {
if (retrofit == null) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface UploadAPIs {
#Multipart
#POST("/upload")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part file, #Part("name") RequestBody requestBody);
}
private void uploadToServer(String filePath) {
Retrofit retrofit = NetworkClient.getRetrofitClient(this);
UploadAPIs uploadAPIs = retrofit.create(UploadAPIs.class);
//Create a file object using file path
File file = new File(filePath);
// Create a request body with file and image media type
RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
// Create MultipartBody.Part using file request-body,file name and part name
MultipartBody.Part part = MultipartBody.Part.createFormData("upload", file.getName(), fileReqBody);
//Create request body with text description and text media type
RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "image-type");
//
Call call = uploadAPIs.uploadImage(part, description);
call.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {
}
#Override
public void onFailure(Call call, Throwable t) {
}
});
}
Try this
#Multipart
#POST(Global.updateProfilePicture)
Call<YOUR_RESPONSE_MODEL> updatePicture(#Header("Authorization") String authorization, #PartMap Map<String, RequestBody> params);
And API call should be like this
public void updatePic(String senderID, String receiverID, String type, File photo) {
mProgressDialog.show();
final Map<String, RequestBody> map = new HashMap<>();
try {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), photo);
map.put("image\"; filename=\"" + photo.getName() + "\"", fileBody);
} catch (Exception e) {
e.printStackTrace();
}
map.put("sender_id", RequestBody.create(MediaType.parse("multipart/form-data"), senderID));
map.put("receiver_id", RequestBody.create(MediaType.parse("multipart/form-data"), receiverID));
map.put("type", RequestBody.create(MediaType.parse("multipart/form-data"), type));
Call<YOUR_RESPONSE_MODEL> call = mApiInterface.updatePicture(ACCESS_TOKEN, map);
call.enqueue(new Callback<YOUR_RESPONSE_MODEL>() {
#Override
public void onResponse(#NonNull Call<YOUR_RESPONSE_MODEL> call, #NonNull Response<YOUR_RESPONSE_MODEL> response) {
if (mContext != null) {
mProgressDialog.dismiss();
// Dismiss Dialog
}
}
#Override
public void onFailure(#NonNull Call<YOUR_RESPONSE_MODEL> call, #NonNull Throwable t) {
if (mContext != null) {
mProgressDialog.dismiss();
}
}
});
}
I got output by doing request as following
UploadAPI Interface
`
#Multipart
#Headers({"TOKEN:XXXX"})
#POST("/api/messages/image")Call<ImageResult>uploadImage(#Part("sender_id")RequestBody sender_id,#Part("receiver_id")RequestBody receiver_id,#Part("type")RequestBody type,#Part MultipartBody.Part image);`
And Following is Method Code, I tried
`
private void uploadToServer(String filePath)
{
Retrofit retrofit = NetworkClient.getRetrofitClient(this, sendImageMsgURL);
UploadAPIs uploadAPIs = retrofit.create(UploadAPIs.class);
File file = new File(filePath);
MultipartBody.Part requestImage = null;
RequestBody requestFile = RequestBody.create(MediaType.parse("mutlipart/form-
data"),file);
requestImage = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
RequestBody sender_id = RequestBody.create(MediaType.parse("multipart/form-data"),
currentID);
RequestBody receiver_id = RequestBody.create(MediaType.parse("multipart/form-data"),
otherID);
RequestBody type = RequestBody.create(MediaType.parse("multipart/form-data"), "image");
Call<ImageResult> call = uploadAPIs.uploadImage(sender_id, receiver_id, type,
requestImage);
call.enqueue(new Callback<ImageResult>()
{
private Call<ImageResult> call;
private Response<ImageResult> response;
#Override
public void onResponse(Call<ImageResult> call, Response<ImageResult> response)
{
this.call = call;
this.response = response;
}
#Override
public void onFailure(Call call, Throwable t) {
Log.d("Error--------- :", t.getMessage());
}
});
}`
Hello everyone I want to post image and other data through Retrofit2.
I am sending data with one image.
All the other info is storing but my image is not storing.while i am testing with postman, it works.
please guide me where I am lacking in my code
This is the postman code snippet that works
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
RequestBody body = RequestBody.create(mediaType, "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"email\"\r\n\r\ntest6#gmail.com\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n123456\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nTest\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"phone\"\r\n\r\n1234567890\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image\"; filename=\"03.JPG\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
Request request = new Request.Builder()
.url("https://"url"/api/v1/sign-up")
.post(body)
.addHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
.addHeader("cache-control", "no-cache")
.addHeader("postman-token", "2dd038d9-5f52-fcd0-9331-445eaf35c230")
.build();
Response response = client.newCall(request).execute();
Below is the postman request image:
this is my Retrofit api
#Multipart
#POST("sign-up")
Call<SignUpResponse> getSignUpResponse(
#Part("email") RequestBody email,
#Part("password") RequestBody password,
#Part("name") RequestBody name,
#Part("phone") RequestBody phone,
#Part MultipartBody.Part image
//#Part("image") RequestBody image // i have thried them both but they didnt work
//#Part("image\"; filename=\"pp.jpg\" ") RequestBody image
);
this is my client area:
private RetrofitClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging); // <-- this is the important line!
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
and this is the part where i am making the request:
RequestBody namePart = RequestBody.create(MultipartBody.FORM, "nameasd");
RequestBody emailPart = RequestBody.create(MultipartBody.FORM, "emailasd#gmai.com");
RequestBody mobilePart = RequestBody.create(MultipartBody.FORM, "123456623");
RequestBody passwordPart = RequestBody.create(MultipartBody.FORM, "123456123");
//String filepath = "/storage/0403-0201/DCIM/Camera/20180926_203219.jpg"; this is the image source
File file = new File(filepath);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
//RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image",file.getName(),reqFile);
Call<SignUpResponse> call = RetrofitClient.getInstance().getApi().getSignUpResponse(emailPart, passwordPart, namePart, mobilePart, body);
call.enqueue(new Callback<SignUpResponse>() {
#Override
public void onResponse(Call<SignUpResponse> call, Response<SignUpResponse> response) {
progressDialog.dismiss();
Log.d(TAG, "onResponse: "+response.body());
Log.d(TAG, "onResponse: meta: " + response.body().getMeta().getStatus());
}
#Override
public void onFailure(Call<SignUpResponse> call, Throwable t) {
Toast.makeText(SignupActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
Log.d(TAG, "onFailure: "+t.getMessage());
}
});
this is the code where i get the data
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// get selected images from selector
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
mResults = data.getStringArrayListExtra(SelectorSettings.SELECTOR_RESULTS);
imagePath = mResults.get(0);
Glide.with(SignupActivity.this)
.load(mResults.get(0))
.into(profileImage);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
I even set it on a view and that works...
We test api in Postman... So my Create Post Answer includes (all Dynamic)
Headers
Simple Strings
Single Image
Array Of Images
Array Of Categories
Array Of Features
Almost all things
Below is the Postman image for api testing...
Headers Image
So for this ...
Below is my Api...
#POST("post-create")
Call<PostCreateResponse> getPostCreateBodyResponse(
#Header("Accept") String accept,
#Header("Authorization") String authorization,
#Body RequestBody file
);
Now Retrofit Client area--->
private Retrofit retrofit;
// This is Client
private RetrofitClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.connectTimeout(100, TimeUnit.SECONDS);
httpClient.readTimeout(100,TimeUnit.SECONDS);
httpClient.writeTimeout(100,TimeUnit.SECONDS);
httpClient.addInterceptor(logging); // <-- this is the important line!
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
This is the way I Made the Request...
/*
* -------------- Retrofit post Create single featured Image Working with MultipartBody -----------
* */
progressDialog.show();
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
builder.addFormDataPart("title", "3 room Current Free")
.addFormDataPart("location", "Dhaka")
.addFormDataPart("latitude", "23.7515")
.addFormDataPart("longitude", "90.3625")
.addFormDataPart("condition", "1")
.addFormDataPart("rent_amount", "123456")
.addFormDataPart("is_negotiable", "0")
.addFormDataPart("available_from", "2018-10-15");
// Categories
for (int categoryId : categories) {
builder.addFormDataPart("categories[]", String.valueOf(categoryId));
}
// Features
for (Integer featureId : features) {
builder.addFormDataPart("features[]", String.valueOf(featureId));
}
// featured Image
if (photoPaths.get(0) != null) {
File featured_image = new File(photoPaths.get(0));
if (featured_image.exists()) {
// If you want to use Bitmap then use this
Bitmap bmp = BitmapFactory.decodeFile(featured_image.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 30, bos);
builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, bos.toByteArray()));
// If you want to use direct file then use this ( comment out the below part and comment the above part )
//builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, featured_image));
}
}
// Images
for (String photoPath : photoPaths) {
if (photoPath != null) {
File images = new File(photoPath);
if (images.exists()) {
builder.addFormDataPart("images[]", images.getName(), RequestBody.create(MultipartBody.FORM, images));
}
}
}
RequestBody requestBody = builder.build();
Call<PostCreateResponse> call = RetrofitClient.getInstance().getApi().getPostCreateBodyResponse(Accept, Authorization, requestBody);
call.enqueue(new Callback<PostCreateResponse>() {
#Override
public void onResponse(Call<PostCreateResponse> call, Response<PostCreateResponse> response) {
progressDialog.dismiss();
Log.d(TAG, "onResponse: response code: retrofit: " + response.code());
}
#Override
public void onFailure(Call<PostCreateResponse> call, Throwable t) {
}
});
/*
* ---------------- Retrofit post Create single featured Image Working with MultipartBody----------------
* */
I hope this will help you all... thanks
get Image like this
Uri mImageUri = data.getData();
// Get the cursor
Cursor cursor = getContentResolver().query(mImageUri,
filePathColumn, null, null, null);
// Move to first row
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageURI = cursor.getString(columnIndex);
cursor.close();
File file = new File(mImageUri.getPath())
RequestBody reqFile = RequestBody.create(okhttp3.MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image",
file.getName(), reqFile);
This is my activity code where i am using multipart to show images, follow this code:
public void uploadimage()
{
String filePath = getRealPathFromURIPath(uri1, DriverDetails.this);
Log.d("hanish123456","File path-> "+filePath);
file1 = new File(filePath);
Log.d("uploadimage", "Filename " + profileimage1);
Bitmap bmp = BitmapFactory.decodeFile(file1.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 30, bos);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("image", profileimage1,
RequestBody.create(MediaType.parse("image/*"), bos.toByteArray()));
RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), profileimage1);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3, TimeUnit.MINUTES)
.readTimeout(3,TimeUnit.MINUTES)
.writeTimeout(3,TimeUnit.MINUTES).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_PATH)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService uploadImage = retrofit.create(ApiService.class);
Log.d("uploadimage", fileToUpload+" "+filename);
Call<ProfileResponse> fileUpload = uploadImage.uploadFile(fileToUpload, filename);
fileUpload.enqueue(new Callback<ProfileResponse>() {
#Override
public void onResponse(Call<ProfileResponse> call, Response<ProfileResponse> response) {
if(response.isSuccessful()){
Toast.makeText(DriverDetails.this,"Successful "+ response.raw().message(), Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(DriverDetails.this, response.raw().message(), Toast.LENGTH_LONG).show();
}
// Toast.makeText(MainActivity.this, "Success " + response.body().getSuccess(), Toast.LENGTH_LONG).show();
Log.d("uploadimage", "No Error ");
}
#Override
public void onFailure(Call<ProfileResponse> call, Throwable t) {
if (t instanceof SocketTimeoutException) {
Log.d("uploadimage", "Error occur " + t.getMessage());
}
}
});
}
there one more simple way to send other data, you can send Hashmap<String,String>
#Multipart
#POST("sign-up")
Call<SignUpResponse> getSignUpResponse(#Part MultipartBody.Part file, #PartMap() Map<String, String> partMap);
MultipartBody.Part.createFormData("file","fileName",RequestBody.create(okhttp3.MediaType.parse("image/*"), file))
I have worked with retrofit file upload. Here by using system.out.println I can track the response body. But can't convert the response to JSON object.
I hereby write my code. Kindly please let me know how do I parse and get the string value using retrofit success message and failure message.
ApiConfig:
public interface ApiConfig {
#Multipart
#POST("general/Candidate/fileUpload")
Call<ResponseBody> upload(
#Header("Authorization") String authorization,
#PartMap Map<String, RequestBody> map,
#Part("id") RequestBody id,
#Part("fileCount") RequestBody fileCount,
#Part("fileType") RequestBody fileType,
#Part("platform") RequestBody platform,
#Part("externalID") RequestBody externalID);
}
ServiceGenerator:
public class ServiceGenerator {
public static final String API_BASE_URL = "http://104.239.173.64/peoplecaddie-api/";
private static Retrofit retrofit = null;
private static OkHttpClient httpClient = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(new Gson()));
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
}
uploadFile1:
private void uploadFile1(Uri fileUri) {
progressDialog.show();
ApiConfig service =
ServiceGenerator.createService(ApiConfig.class);
File file = FileUtils.getFile(this, fileUri);
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
Map<String, RequestBody> map = new HashMap<>();
map.put("fileContent0\"; filename=\"" + file.getName() + "\"", requestFile);
MultipartBody.Part body =
MultipartBody.Part.createFormData("fileContent0", file.getName(), requestFile);
String idStr = "1743";
String fileCountStr = "1";
String fileTypeStr = "SAMPLE";
String platformStr = "Android";
String externalIDStr = "portpolio";
RequestBody idReq =
RequestBody.create(
MediaType.parse("multipart/form-data"), idStr);
RequestBody fileCountReq =
RequestBody.create(
MediaType.parse("multipart/form-data"), fileCountStr);
RequestBody fileTypeReq =
RequestBody.create(
MediaType.parse("multipart/form-data"), fileTypeStr);
RequestBody platformReq =
RequestBody.create(
MediaType.parse("multipart/form-data"), platformStr);
RequestBody externalIDReq =
RequestBody.create(
MediaType.parse("multipart/form-data"), externalIDStr);
// finally, execute the request
Call<ResponseBody> call = service.upload("817b6ce98fd759e7f148b948246df6c1", map, idReq, fileCountReq, fileTypeReq, platformReq, externalIDReq);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
try {
System.out.println("Rrespppppp--->"+response.body().string());
Log.e("response", "response------------------>" + response.body().string());
JSONObject profileFileUploadResponse = new JSONObject(String.valueOf(response.body()));
Log.e("retro", "retroFileResp------------------>" + profileFileUploadResponse);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
}
Here upload file method I can track the response using. This works fine.
System.out.println("Rrespppppp--->"+response.body().string());
But while try to convert the JSON Object it will not work the error code is below. And please let me know how do i parse and get the success and failure response value using this code.
Log.e("response", "response------------------>" + response.body().string());
JSONObject profileFileUploadResponse = new JSONObject(String.valueOf(response.body()));
Log.e("retro", "retroFileResp------------------>" + profileFileUploadResponse);
Thanks in Advance.
**You have to use Gson to get JsonObject response like below.**
public interface getProfileInfo {
#GET("users/{userid}")
Call<JsonObject> getProfileData(#Path("userid") String userId);
}
private void getUserProfileInfo(String userId)
{
getProfileInfo postService=RetrofitApi.makeNetworkRequest().create(getProfileInfo.class);
Call<JsonObject> call = postService.getProfileData(userId);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
System.out.println("user Info :" + response.body().getAsJsonObject());
setUserData(response.body().getAsJsonObject());
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
// Log error here since request failed
System.out.println("Error :" + t.getMessage());
}
});
}
Modified your code. Please try. You will get json object in result
Call<ResponseBody> call = service.upload("817b6ce98fd759e7f148b948246df6c1", map, idReq, fileCountReq, fileTypeReq, platformReq, externalIDReq);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
try {
System.out.println("Rrespppppp--->"+response.body().string());
Log.e("response", "response------------------>" + response.body().string());
//JSONObject profileFileUploadResponse = new JSONObject(String.valueOf(response.body()));
ResponseBody result = response.body();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
Retrofit Response is already in json format you can get item by
{ "result": [{ "fileId": 852, "status": 1, "pcData": { "id": 635, "filename": "IMG_20161122_175344.jpg", "filepath": "uploads\/peoplecaddie\/files\/1743_1480742360_IMG_20161122_175344.jpg" } }] }
String fileid=response.body().getresult(0).getFileId();
String status=response.body().getresult(0).getStatus();
You can only call response.body().string() once. From the ResponseBody docs --
The response body can be consumed only once.
You try to consume the body on both of the following two lines
Log.e("response", "response------------------>" + response.body().string());
JSONObject profileFileUploadResponse = new JSONObject(String.valueOf(response.body()));
You can read it once into a variable and reuse that --
final String body = response.body().string();
Log.e("response", "response------------------>" + body);
JSONObject profileFileUploadResponse = new JSONObject(body);
That should fix your problem, but if you don't want to go further and don't want to deal with creating the JSONObject yourself, one of the benefits of retrofit it does deserialization as well. You are already configuring a gson converter to your retrofit, so you should be able to update your call to --
#Multipart
#POST("general/Candidate/fileUpload")
Call<ReturnObject> upload(...)
where ReturnObject is the POJO you want to deserialize to. You will have to update your response handler as well, to expect a ReturnObject type.
Try this, It will work
Change Call Type as JsonElement
#GET("LoginAPI")
Call<JsonElement> getLogin(#Query("Username") String userName,
#Query("Password") String password);
Get Json object from the response
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
try {
JSONObject object = new JSONObject(response.body().toString());
textView.setText(object.toString());
} catch (JSONException e) {
e.printStackTrace();
textView.setText(e.getMessage());
}
}
I'm trying to down/upload a file with retrofit 2 but can't find any tutorials examples on how to do so.
My code for downloading is:
#GET("documents/checkout")
public Call<File> checkout(#Query(value = "documentUrl") String documentUrl, #Query(value = "accessToken") String accessToken, #Query(value = "readOnly") boolean readOnly);
and
Call<File> call = RetrofitSingleton.getInstance(serverAddress)
.checkout(document.getContentUrl(), apiToken, readOnly[i]);
call.enqueue(new Callback<File>() {
#Override
public void onResponse(Response<File> response,
Retrofit retrofit) {
String fileName = document.getFileName();
try {
System.out.println(response.body());
long fileLength = response.body().length();
InputStream input = new FileInputStream(response.body());
File path = Environment.getExternalStorageDirectory();
File file = new File(path, fileName);
BufferedOutputStream output = new BufferedOutputStream(
new FileOutputStream(file));
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
} catch (IOException e) {
String logTag = "TEMPTAG";
Log.e(logTag, "Error while writing file!");
Log.e(logTag, e.toString());
}
}
#Override
public void onFailure(Throwable t) {
// TODO: Error handling
System.out.println(t.toString());
}
});
I've tried with Call and Call but nothing seems to work.
The server-side code writes the file's bytes into HttpServletResponse's output stream after setting the headers and mime type correctly.
What am I doing wrong?
Finally, the upload code:
#Multipart
#POST("documents/checkin")
public Call<String> checkin(#Query(value = "documentId") String documentId, #Query(value = "name") String fileName, #Query(value = "accessToken") String accessToken, #Part("file") RequestBody file);
and
RequestBody requestBody = RequestBody.create(MediaType.parse(document.getMimeType()), file);
Call<String> call = RetrofitSingleton.getInstance(serverAddress).checkin(documentId, document.getFileName(), apiToken, requestBody);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response, Retrofit retrofit) {
System.out.println(response.body());
}
#Override
public void onFailure(Throwable t) {
System.out.println(t.toString());
}
});
Thanks!
Edit:
After the answer, downloading only yields a corrupted file (without the #Streaming), uploading doesn't as well. When I use the above code, the server returns a 400 error. After changing it to
RequestBody requestBody = RequestBody.create(MediaType.parse(document.getMimeType()), file);
MultipartBuilder multipartBuilder = new MultipartBuilder();
multipartBuilder.addFormDataPart("file", document.getFileName(), requestBody);
Call<String> call = RetrofitSingleton.getInstance(serverAddress).checkin(documentId, document.getFileName(), apiToken, multipartBuilder.build());
, the request executes but the backend doesn't seem to receive a file.
Backend code:
#RequestMapping(value = "/documents/checkin", method = RequestMethod.POST)
public void checkInDocument(#RequestParam String documentId,
#RequestParam String name, #RequestParam MultipartFile file,
#RequestParam String accessToken, HttpServletResponse response)
What am I doing wrong? I was able to use the backend from plain Java with the Apache HttpClient:
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", new File("E:\\temp\\test.jpg"));
HttpEntity httpEntity = builder.build();
System.out.println("HttpEntity " + EntityUtils.toString(httpEntity.));
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(httpEntity);
Edit v2
For anyone interested, both up- and downloading work now: These are the solutions:
Service:
#GET("documents/checkout")
public Call<ResponseBody> checkout(#Query(value = "documentUrl") String documentUrl, #Query(value = "accessToken") String accessToken, #Query(value = "readOnly") boolean readOnly);
#Multipart
#POST("documents/checkin")
public Call<String> checkin(#Query(value = "documentId") String documentId, #Query(value = "name") String fileName, #Query(value = "accessToken") String accessToken, #Part("file") RequestBody file);
Download Code:
Call<ResponseBody> call = RetrofitSingleton.getInstance(serverAddress)
.checkout(document.getContentUrl(), apiToken, readOnly[i]);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response,
Retrofit retrofit) {
String fileName = document.getFileName();
try {
File path = Environment.getExternalStorageDirectory();
File file = new File(path, fileName);
FileOutputStream fileOutputStream = new FileOutputStream(file);
IOUtils.write(response.body().bytes(), fileOutputStream);
} catch (IOException e) {
Log.e(logTag, "Error while writing file!");
Log.e(logTag, e.toString());
}
}
#Override
public void onFailure(Throwable t) {
// TODO: Error handling
System.out.println(t.toString());
}
});
Upload Code:
Call<String> call = RetrofitSingleton
.getInstance(serverAddress).checkin(documentId,
document.getFileName(), apiToken,
multipartBuilder.build());
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response,
Retrofit retrofit) {
// Handle response here
}
#Override
public void onFailure(Throwable t) {
// TODO: Error handling
System.out.println("Error");
System.out.println(t.toString());
}
});
For downloading, you can use ResponseBody as your return type --
#GET("documents/checkout")
#Streaming
public Call<ResponseBody> checkout(#Query("documentUrl") String documentUrl, #Query("accessToken") String accessToken, #Query("readOnly") boolean readOnly);
and you can get the ResponseBody input stream in your call back --
Call<ResponseBody> call = RetrofitSingleton.getInstance(serverAddress)
.checkout(document.getContentUrl(), apiToken, readOnly[i]);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response,
Retrofit retrofit) {
String fileName = document.getFileName();
try {
InputStream input = response.body().byteStream();
// rest of your code
Your upload looks okay at first glance if you server handles multipart messages correctly. Is it working? If not, can you explain the failure mode? You also might be able to simplify by not making it multipart. Remove the #Multipart annotation and convert #Path to #Body --
#POST("documents/checkin")
public Call<String> checkin(#Query("documentId") String documentId, #Query("name") String fileName, #Query("accessToken") String accessToken, #Body RequestBody file);
I am using retrofit 2.0.0-beta2 and I had an issue uploading image by using multipart request. I solved it by using this answer: https://stackoverflow.com/a/32796626/2915075
The key for me was to use standard POST with MultipartRequestBody instead of #Multipart annotated request.
Here is my code:
Retrofit service class
#POST("photo")
Call<JsonElement> uploadPhoto(#Body RequestBody imageFile, #Query("sessionId"));
Usage from activity, fragment:
RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), imageFile);
MultipartBuilder multipartBuilder = new MultipartBuilder();
multipartBuilder.addFormDataPart("photo", imageFile.getName(), fileBody);
RequestBody fileRequestBody = multipartBuilder.build();
//call
mRestClient.getRetrofitService().uploadProfilePhoto(fileRequestBody, sessionId);
i have the same problems, and i found a solution to upload files, that described here
Is it possible to show progress bar when upload image via Retrofit 2
Also I had this problem, This is how i try to solve my problem (RETROFIT 2 )
//1. What We Need From Server ( upload.php Script )
public class FromServer {
String result;
}
//2. Which Interface To Communicate Our upload.php Script?
public interface ServerAPI {
#Multipart
#POST("upload.php")//Our Destination PHP Script
Call<List<FromServer>> upload(
#Part("file_name") String file_name,
#Part("file") RequestBody description);
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl("http://192.168.43.135/retro/") // REMEMBER TO END with /
.addConverterFactory(GsonConverterFactory.create())
.build();
}
//3. How To Upload
private void upload(){
ServerAPI api = ServerAPI.retrofit.create(ServerAPI.class);
File from_phone = FileUtils.getFile(Environment.getExternalStorageDirectory()+"/aa.jpg"); //org.apache.commons.io.FileUtils
RequestBody to_server = RequestBody.create(MediaType.parse("multipart/form-data"), from_phone);
api.upload(from_phone.getName(),to_server).enqueue(new Callback<List<FromServer>>() {
#Override
public void onResponse(Call<List<FromServer>> call, Response<List<FromServer>> response) {
Toast.makeText(MainActivity.this, response.body().get(0).result, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<List<FromServer>> call, Throwable t) { }
});
}
//4. upload.php
<?php
$pic = $_POST['file_name'];
$pic = str_replace("\"", "", $pic); //REMOVE " from file name
if(file_exists($pic)){unlink($pic);}
$f = fopen($pic, "w");
fwrite($f,$_POST['file']);
fclose($f);
$arr[] = array("result"=>"Done");
print(json_encode($arr));
?>
You can refer tutorial for Image Download using Retrofit 2.0
For the time being you can refer following functions for image download:
void getRetrofitImage() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitImageAPI service = retrofit.create(RetrofitImageAPI.class);
Call<ResponseBody> call = service.getImageDetails();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
try {
Log.d("onResponse", "Response came from server");
boolean FileDownloaded = DownloadImage(response.body());
Log.d("onResponse", "Image is downloaded and saved ? " + FileDownloaded);
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
}
Following is the file handling part image download using Retrofit 2.0
private boolean DownloadImage(ResponseBody body) {
try {
Log.d("DownloadImage", "Reading and writing file");
InputStream in = null;
FileOutputStream out = null;
try {
in = body.byteStream();
out = new FileOutputStream(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}
catch (IOException e) {
Log.d("DownloadImage",e.toString());
return false;
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
int width, height;
ImageView image = (ImageView) findViewById(R.id.imageViewId);
Bitmap bMap = BitmapFactory.decodeFile(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
width = 2*bMap.getWidth();
height = 6*bMap.getHeight();
Bitmap bMap2 = Bitmap.createScaledBitmap(bMap, width, height, false);
image.setImageBitmap(bMap2);
return true;
} catch (IOException e) {
Log.d("DownloadImage",e.toString());
return false;
}
}
I hope it will help. All the best. Happy Coding :)