I'm using Retrofit v.2.2.0 to upload a picture to my server but the server returns a null value stating no image has been uploaded. The logs shows the image is uploaded and the file name is correct when uploaded. What can be the problem yet it works in postman?
UploadProfilePicture.java
public class UploadProfilePicture extends ContextWrapper {
private GetOnUpload onUpload;
private File imageFile,filesDir,file;
private Uri fileUri;
private String profilePic = "profile_pic";
private String fileName;
private ParcelFileDescriptor parcelFileDescriptor;
private FileDescriptor fileDescriptor;
private Bitmap profileImage;
private OutputStream os;
private OkHttpLogClientAPI okHttpLogClientAPI;
private GetOnUpload mInterfaceService;
public UploadProfilePicture(Context base) {
super(base);
okHttpLogClientAPI = new OkHttpLogClientAPI(getBaseContext());
mInterfaceService = okHttpLogClientAPI.logger().create(GetOnUpload.class);
}
public void uploadPic(Uri fileUri,String fileName, final OnSetUploadProfilePic setOnUpload) {
//Build Req estBodies for the map object and a MultipartBody.Part to encapsulate the prof_pic_drawer
this.fileUri = fileUri;
this.fileName = fileName;
try {
getBitmapFromUri();
} catch (IOException e) {
e.printStackTrace();
}
file = persistImage();
RequestBody finalRequestBody = builder.build();
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), getBytesFromBitmap(profileImage));
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", "avatar.jpg", requestFile);
Call<ResponseUserModel> call = mInterfaceService.upload(body);
call.enqueue(new Callback<ResponseUserModel>() {
@Override
public void onResponse(Call<Response> call, Response<Response> response) {
if (response.isSuccessful()) {
setOnUpload.uploadMessage(response.body());
} else {
Toast.makeText(getBaseContext(), getString(R.string.failed_to_upload), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
Toast.makeText(getBaseContext(), getString(R.string.failed_to_upload), Toast.LENGTH_SHORT).show();
}
});
}
}
public static byte[] getBytesFromBitmap(Bitmap bitmap) {
if (bitmap!=null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
return stream.toByteArray();
}
return null;
}
private MultipartBody.Part prepareFilePart() {
//TODO: Use FileUtils to get the actual file by uri
try {
getBitmapFromUri();
file = persistImage();
} catch (IOException e) {
e.printStackTrace();
}
try {
RequestBody requestFile = RequestBody.create(
MediaType.parse(getBaseContext().getContentResolver().getType(fileUri)), file);
return MultipartBody.Part.createFormData("file", file.getName(), requestFile);
} catch (NullPointerException e) {
Toast.makeText(getBaseContext(), "" + e.getMessage(), Toast.LENGTH_SHORT).show();
return null;
}
}
private RequestBody createPartFromString(String descriptionString) {
return RequestBody.create(MultipartBody.FORM, descriptionString);
}
private void getBitmapFromUri() throws IOException {
profileImage = MediaStore.Images.Media.getBitmap(this.getContentResolver(), fileUri);
}
private File persistImage() {
filesDir = getFilesDir();
imageFile = new File(filesDir, fileName + ".jpg");
OutputStream os;
try {
os = new FileOutputStream(imageFile);
profileImage.compress(Bitmap.CompressFormat.JPEG, 70, os);
os.flush();
os.close();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
}
return imageFile;
}}
GetOnUpload.java
public interface GetOnUpload {
@Multipart
@POST(Constants.UPLOAD_URL)
Call<Response> upload(@Part MultipartBody.Part file);}
Log
http://local.com/api/v1/avatar http/1.1 11-14 18:40:02.742 8851-9593/com.local.test D/OkHttp: Content-Type: multipart/form-data; boundary=d43da080-f2c3-4743-8cfd-9526cc0bd2f7 11-14 18:40:02.742 8851-9593/com.local.test D/OkHttp: Content-Length: 12424 11-14 18:40:02.743 8851-9593/com.local.test D/OkHttp: --d43da080-f2c3-4743-8cfd-9526cc0bd2f7 11-14 18:40:02.743 8851-9593/com.local.test D/OkHttp: Content-Disposition: form-data; name="file"; filename="avatar.jpg" 11-14 18:40:02.743 8851-9593/com.local.test D/OkHttp: Content-Type: multipart/form-data 11-14 18:40:02.743 8851-9593/com.local.test D/OkHttp: Content-Length: 12201 11-14 18:40:02.743 8851-9593/com.local.test D/OkHttp: 11-14 18:40:02.744 8851-9593/com.local.test D/OkHttp: --d43da080-f2c3-4743-8cfd-9526cc0bd2f7-- 11-14 18:40:02.744 8851-9593/com.local.test D/OkHttp: --> END POST (12424-byte body)
11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: <-- 200 OK http://local.com/api/v1/avatar (587ms) 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Server: nginx/1.10.3 (Ubuntu) 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Content-Type: application/json 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Transfer-Encoding: chunked 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Connection: keep-alive 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Cache-Control: no-cache, private 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: Date: Tue, 14 Nov 2017 15:40:03 GMT 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: X-RateLimit-Limit: 60 11-14 18:40:03.332 8851-9593/com.local.test D/OkHttp: X-RateLimit-Remaining: 59 11-14 18:40:03.333 8851-9593/com.local.test D/OkHttp: {"user":"Failed","status":"Image file not uploaded"}
ImageFilePath
ChooseImg
Interface
Add this code in your Activity
It seems there is a problem with OKHttp so when posting a file and data to the server with retrofit use this format
This example worked for me