5

I've been trying to implement profile photo upload feature by Android Retrofit + SpringMVC. Java server unable to respond Retrofit API call. Related code snippet is given below:

ApiInterface

@Multipart
@POST("user/profileImage")
Call<ResponseBody> uploadImage(@Part MultipartBody.Part image, @Part("name") RequestBody name);

uploadToServer

public void uploadToServer(){
    //Get retrofit client
    Retrofit retrofit = ApiClient.getClient();
    //Get API interface
    ApiInterface apiInterface = retrofit.create(ApiInterface.class);
    // Get image parts
    MultipartBody.Part imageParts = bitmapToMultipart(imageBitmap);
    //Get image name
    RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "ProfileImage");
    //Call image upload API
    Call<ResponseBody> call = apiInterface.uploadImage(imageParts,name);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            ResponseBody body = response.body();
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

bitmapToMultipart

public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){
    File file = null;
    try {
        //create a file to write bitmap data
        file = new File(this.getCacheDir(), "imageBitmap");
        file.createNewFile();

        //Convert bitmap to byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
        byte[] bitmapdata = bos.toByteArray();

        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();
    }catch(IOException e){
        e.printStackTrace();
    }
    RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
    MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);

    return body;
}

Java SpringMVC controller

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
    public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestBody RequestBody name)throws Exception{
        return "";
    }
}

Problem is: Request not even reaching to java server.

Almett
  • 876
  • 2
  • 11
  • 34
  • Your bitmapToMultipart() should `return null;` in that catch block. And where you call that function you should check the return value for null. And not continue if it is null. Please adapt your code. – greenapps Nov 24 '17 at 09:57
  • Further remove the ByteArrayOutputStream and compress your bitmap to `fos` directly. – greenapps Nov 24 '17 at 09:58
  • `file.createNewFile();`. Remove that line. – greenapps Nov 24 '17 at 10:00
  • @greenapps Return type must be `MultipartBody.Part` because which is return type of API parameter. Image can be selected and display in client side, problem is the server no response to the request. I don't think this helps me. – Almett Nov 24 '17 at 12:48
  • Yes i see. But it would help you to make your code more robust. And you can return null there even for MultipartBody.Part type. Please add all i asked for. – greenapps Nov 24 '17 at 12:51
  • I got it. Thanks for your optimization advise.☺ – Almett Nov 24 '17 at 12:59
  • try this library and check once https://github.com/gotev/android-upload-service – Manohar Dec 01 '17 at 13:23

4 Answers4

5

In your uploadToServer() function media type should be "multipart/form-data" in place of "text/plain" for field name...

//Get image name
    RequestBody name = RequestBody.create(MediaType.parse("multipart/form-data"), "ProfileImage");

In your bitmapToMultipart() function media type should be "multipart/form-data". ("image/*" should also work but if not "multipart/form-data" will definitely work)

refer - How to Upload Image file in Retrofit 2

And in your spring controller you should use @RequestParam in place of @Requestbody

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
    public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestParam String name)throws Exception{
        return "";
    }
}
vsoni
  • 2,828
  • 9
  • 13
0

Please change your

RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);

to

RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);

ie you bitmapToMultipart function should be like,

public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){
    File file = null;
    try {
        //create a file to write bitmap data
        file = new File(this.getCacheDir(), "imageBitmap");
        file.createNewFile();

        //Convert bitmap to byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
        byte[] bitmapdata = bos.toByteArray();

        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();
    }catch(IOException e){
        e.printStackTrace();
    }
    RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
    MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);

    return body;
}
Sachin Varma
  • 2,175
  • 4
  • 28
  • 39
0

ApiInterface

@Multipart
@POST("user/profileImage")
Call<ResponseBody> uploadImage(@Part("image") MultipartBody.Part image, @Part("name") RequestBody name);

uploadToServer

public void uploadToServer(){
    //Get retrofit client
    Retrofit retrofit = ApiClient.getClient();
    //Get API interface
    ApiInterface apiInterface = retrofit.create(ApiInterface.class);
    // Get image parts
    MultipartBody.Part imageParts = bitmapToMultipart(imageBitmap);
    //Get image name
    RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "ProfileImage");
    //Call image upload API
    Call<ResponseBody> call = apiInterface.uploadImage(imageParts,name);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            ResponseBody body = response.body();
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

bitmapToMultipart

public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
        byte[] bitmapdata = bos.toByteArray();

    RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), bitmapdata);
    MultipartBody.Part body = MultipartBody.Part.createFormData("upload", "name", reqFile);

    return body;
}  

Java SpringMVC controller

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
    public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestParam String name)throws Exception{
        return "";
    }
}
kunwar97
  • 775
  • 6
  • 14
0
  1. first you should check android client upload file is OK.eg:use compress quality 80

    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);

  2. change MediaType and debug at client RequestBody have data
  3. Debug at server check receive request data
hai046
  • 61
  • 1
  • 7