2

I am trying to upload Image via Retrofit to S3 via Spring. So, it's basically 2 tasks.

  1. Pass Image to Spring API
  2. From Spring API upload it to S3 Server.

I know how to upload the Image to S3 and it works fine.

My Problem is the first part. I have tried many solutions on net but didn't work.Here's my code ->

On Android side, first I am Getting file and Uploading it to Spring API ->

private void UploadFiles() {
        File uploadFile = fileArrayList.get(0);
        if (uploadFile != null) {
            Log.d(TAG, "UploadFiles: File Name is -> " + uploadFile.getName());
            RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), uploadFile);
            MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("image", uploadFile.getName(), requestFile);
            cropImageRequest.setCropId(uploadFile.getParent());
            cropImageRequest.setCropImage(multipartBody);
            FarmerResponse farmerResponse = UserAuth.getInstance(this).getCurrentUser();
            Api.uploadCropImage(farmerResponse.getAuthToken(), farmerResponse.getFarmer().getId(), cropImageRequest, new Callback<BasicResponse>() {
                @Override
                public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
                    Log.d(TAG, "onResponse: Success : " + response.toString());
                }

                @Override
                public void onFailure(Call<BasicResponse> call, Throwable t) {
                    Log.d(TAG, "onResponse: Failure : " + t.getMessage());
                }
            });
        }
    }

I have created a cropImageRequest.java which is basically a POJO class for Request Body. Here's my POJO class, it contains Image and ImageId. ->

import okhttp3.MultipartBody;

public class CropImageRequest {

    private String CropId;
    private MultipartBody.Part CropImage;

    public CropImageRequest() {

    }

    public void setCropId(String cropId) {
        CropId = cropId;
    }

    public void setCropImage(MultipartBody.Part cropImage) {
        CropImage = cropImage;
    }

    public CropImageRequest(String cropId, MultipartBody.Part cropImage) {
        CropId = cropId;
        CropImage = cropImage;
    }

    public String getCropId() {
        return CropId;
    }

    public MultipartBody.Part getCropImage() {
        return CropImage;
    }
}

This is my API declaration, inside API Class. ->

public interface UploadCropImageApi {
        @POST(UPLOAD_FILE_TO_AWS_URL)
        Call<BasicResponse> uploadCropImage(
                @Header(MOBILE_AUTH) String authToken,
                @Header(FARMER_ID) String farmerId,
                @Body CropImageRequest cropImageRequest);
    }
        public static void uploadCropImage(String authToken, String farmerId, CropImageRequest cropImageRequest, Callback<BasicResponse> callback) {
                UploadCropImageApi uploadCropImageApi = retrofit.create(UploadCropImageApi.class);
                Call<BasicResponse> call = uploadCropImageApi.uploadCropImage(authToken, farmerId, cropImageRequest);
                call.enqueue(callback);
    }

On Spring side I have developed a controller, which handles API Request and Uploads Passed Image to S3 ->

@RequestMapping(value = "/UploadCropImage",method = RequestMethod.POST,produces = "application/json")
    @ResponseBody
    public String UploadImage(@RequestBody CropImageRequest cropImageRequest,HttpServletRequest request) {
        uuid = new UUIDUtils();
        fileUtils = new FileUtils();
        try {
            String KeyName = uuid.GenerateUUID(fileUtils.convert(cropImageRequest.getCropImage()));
            System.out.println(KeyName);
            return mAmazonClient.uploadImage(KeyName,cropImageRequest.getCropImage());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

This is my Convert function which Converts MultiPart File into File.

public String convert(MultipartFile file) throws IOException {
        if(file!=null){
            File convFile = new File(file.getOriginalFilename());
            convFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(convFile);
            fos.write(file.getBytes());
            fos.close();
            return convFile.getName();
        }
        else{
            System.out.println("Supplied File is null");
            return null;
        }       
    }

The Problem is that I am getting Null Pointer Exception, at Spring side, conditional check. Which means The File is not getting uploaded. On Android Side I have verified by printing out the file name and it's printing correct file name. BTW I am uploading .WebP format file, I dont think that's creating any issue here. Thanks for help in advance.

Avi Patel
  • 475
  • 6
  • 23

1 Answers1

1

you are sending your information using multipart/form-data so try to use

@ModelAttribute

instead of

@RequestBody

the method signature will be

public String UploadImage(@ModelAttribute CropImageRequest cropImageRequest,HttpServletRequest request)
stacker
  • 4,317
  • 2
  • 10
  • 24
  • i want to send data via Request Body only, because Spring has Encrypts the Request Body and yes i have change my code to send "image/*" instead of "multipart/form-data". – Avi Patel Nov 16 '18 at 19:08
  • if you are using image/* the whole body will be treated as an image, if so, only send the image and change your method signature to get MultipartFile file – stacker Nov 16 '18 at 19:22
  • I am new to spring can you tell me how can i send this POJO inside RequestBody? – Avi Patel Nov 16 '18 at 19:25
  • can you make sure to edit your code as described above? you will be able to send the POJO inside – stacker Nov 16 '18 at 19:28
  • But you are using ModelAttribute instead of requestBody. I dont want that, I have tried replacing ModelAttribute with RequestBody. it didn't work. – Avi Patel Nov 16 '18 at 19:30
  • did you use multipart/form-data because it's important – stacker Nov 16 '18 at 19:41
  • Yes i have used it, did not work, still getting null values on Spring side. – Avi Patel Nov 16 '18 at 19:43
  • can you print the exception msg here? – stacker Nov 16 '18 at 19:46
  • it's null pointer exception as cropImageRequest have null values for both cropId and cropImage. – Avi Patel Nov 16 '18 at 19:47
  • did you activate Multipart in retrofit, @Multipart? – stacker Nov 16 '18 at 19:56
  • why? I am not using Parts, i am sending POJO. – Avi Patel Nov 16 '18 at 19:58
  • I think you misunderstood your problem, have a look at https://stackoverflow.com/questions/39953457/how-to-upload-image-file-in-retrofit-2 – stacker Nov 16 '18 at 20:00
  • yes i got your point, but i am not sending the Request in parts according to your latest answer. i am just setting up the POJO and sending itin one Request Body. – Avi Patel Nov 16 '18 at 20:02
  • the answer above should make sure your server side works, you need to make sure to send the appropriate request, in the code you provided you were creating Parts from the images, so obviously you are trying to use Multipart {MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("image", uploadFile.getName(), requestFile);} – stacker Nov 16 '18 at 20:05