0

Hi I am trying to upload an image to Linkedin via Spring RestTemplate, the steps followed are as follows 1.Initialize the upload and the upload url 2.Use the upload url to PUT the image linked in server

below is the method for step 2

public String uploadImageToURL(MultipartFile file, String uploadURL) throws IOException {
    HttpHeaders headers = new HttpHeaders();
    headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    headers.add("Authorization", "Bearer Redacted");

    MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    body.add("file", file.getBytes());

    HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(body, headers);
    try {
        ResponseEntity<String> resp = new RestTemplate().exchange(uploadURL, HttpMethod.PUT, reqEntity, String.class);
    } catch (HttpClientErrorException e) {
        e.printStackTrace();
    }
}

the method is giving -

org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [no body]

I am not able to figure out what's wrong here also from the documentation of linkedin apis its not clear they have given a basic curl request which working fine on postman but programmatically its not working

Curl for the above method as per documentation

Any help is appreciated, I have tried giving content-type to header as image/png but no effect.

PS: I have already referred this link Linkedin v2 API Image upload get error 400 Bad Request but its not helping

Bruce_Wayne
  • 1,564
  • 3
  • 18
  • 41

2 Answers2

0

You can try something like the following: 1- Generate and print/get the url that the image has to be uploaded to (first part of the upload process). 2- Try to upload it by using the curl tool, just like in the docs. If 2 works then you know the preceding step is working fine and the problem is on the method you posted. Otherwise, you know you have to look elsewhere (steps before 2).

In the case that curl works, then it might just be that the server of the upload link accepts requests not in HTTP(S) but FTP or something similar. In that case you would need to find a solution for that protocol.

Regarding your current implementation:

  • using RestTemplate is discouraged since it will soon no longer be supported.
  • use WebClientinstead: link to defining the body of a request
  • don't use MultiValueMap since it adds the file as a key-value pair and judging from the example on the docs there is no "file" key like you have defined.

As a last resort, in case the curl call works and nothing else does, you could create a simple Bash/Shell script that is called only for part 2 of the process. Happy coding! :)

mrkachariker
  • 411
  • 4
  • 9
  • “_using RestTemplate is discouraged_” can you cite your source here? I’m not aware of such a deprecation. – Abhijit Sarkar Oct 20 '22 at 02:30
  • [NOTE: As of 5.0 this class is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the org.springframework.web.reactive.client.WebClient which has a more modern API and supports sync, async, and streaming scenarios.](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html) – mrkachariker Oct 20 '22 at 02:33
  • Thanks, but since they don’t publish the WebClient as a separate artifact, you’ve to bring in the whole reactive web baggage simply to use that one class. – Abhijit Sarkar Oct 20 '22 at 04:10
0

Found the solution, actually using ByteArrayResource and right content-type solved the problem, here is the updated code

private void uploadImage(MultipartFile file, String token, String uploadURL) throws IOException {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Bearer " + token);
    headers.add("X-Restli-Protocol-Version", "2.0.0");
    headers.add("Content-Type", file.getContentType());

    ByteArrayResource bytes = new ByteArrayResource(file.getBytes()) {
        @Override
        public String getFilename() {
            return file.getName();
        }
    };
    HttpEntity<ByteArrayResource> reqEntity = new HttpEntity<ByteArrayResource>(bytes, headers);
    try {
        ResponseEntity<String> imageUpload = new RestTemplate().exchange(uploadURL, HttpMethod.PUT, reqEntity, String.class);
    } catch (HttpClientErrorException e) {
        e.printStackTrace();
    }
}

I refereed this question for insights.

Bruce_Wayne
  • 1,564
  • 3
  • 18
  • 41