Search code examples
javaspringspring-bootresttemplate

not able to call upload file API using RestTemplate


Using RestTemplate I am trying to call some API that accepts image file, that it further writes/uploads on its server.

Below is the API snapshot in postman that I am trying to call using RestTemplate

enter image description here

Now to call this API I wrote a code that uses RestTemplate to call this API. To collect the Multipart image , I created a simple bean class, that has single member variable private MultipartFile image; with its getters and setters.

public class ImageClass implements Serializable{

    private static final long serialVersionUID = 1L;
    private MultipartFile image;
    public MultipartFile getImage() {
        return image;
    }
    public void setImage(MultipartFile image) {
        this.image = image;
    }
}

Next I used this file in @modelAttribute in a below code:

@PutMapping(value="api/update/image/{id}")
public String uploadFile(@PathVariable(name = "id")String id, @ModelAttribute ImageClass imageClass) {
    MultipartFile file = imageClass.getImage();
    RestTemplate restTemplate = new RestTemplate();
    String url = "http://172.18.5.19:8082/api/upload/image/23";
    String accessToken = getCrmAccessToken();
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Bearer "+accessToken);
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    MultiValueMap<String, Object> parts = 
            new LinkedMultiValueMap<String, Object>();
    try {
        parts.add("image", new ByteArrayResource(file.getBytes()));
    } catch (IOException e) {
        e.printStackTrace();
    }
    HttpEntity<MultiValueMap<String, Object>> requestEntity =
            new HttpEntity<MultiValueMap<String, Object>>(parts, headers);

    ResponseEntity<String> response =
            restTemplate.exchange(url, 
                    HttpMethod.PUT, requestEntity, String.class);

    if (response != null && !response.getBody().trim().equals("")) {
        return response.getBody();
    }

    return "error";
}

Now I am getting a below response on console:

org.springframework.web.client.HttpClientErrorException$BadRequest: 400 : "{"timestamp":1727438078594,"status":400,"error":"Bad Request","path":"/api/upload/image/23"}"
    at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:103) ~[spring-web-6.0.9.jar:6.0.9]

Via my API this actual API should be called, so I am also trying it as PUT request in postman like below

enter image description here

Am I giving it correct headers.. It required bearer token (no issue in bearer token generation), all other apis working fine with that bearer token generation code. Only this api is causing issue. What should I do to resolve this issue

I even try with @RequestParam("image") final MultipartFile image instead of @modelAttribute. But same response is coming.


Solution

  • Issue could be because the ByteArrayResource does not have a filename.

    Here is a suggestion.

    Code suggestion:

    import org.springframework.core.io.ByteArrayResource;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    
    public class ImageUploadController {
    
        @PutMapping(value = "api/update/image/{id}")
        public String uploadFile(@PathVariable(name = "id") String id, @ModelAttribute ImageClass imageClass) {
            MultipartFile file = imageClass.getImage();
            RestTemplate restTemplate = new RestTemplate();
            String url = "http://172.18.5.19:8082/api/upload/image/23";
            String accessToken = getCrmAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Bearer " + accessToken);
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    
            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            try {
                parts.add("image", new ByteArrayResource(file.getBytes()) {
                    @Override
                    public String getFilename() {
                        return file.getOriginalFilename();
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
                return "error";
            }
    
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);
    
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class);
    
            if (response != null && !response.getBody().trim().equals("")) {
                return response.getBody();
            }
    
            return "error";
        }
    }