Search code examples
springspring-bootmultipartform-dataresttemplate

How do I send a multipartFile using spring RestTemplate?


I am trying to POST a file to from one SpringBoot app to anothe SpringBoot app. The enpoint I am trying to reach looks like

@PostMapping(
        value = "/upload",
        consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ArmResponse<JobData>> uploadInvoices(@RequestParam("file") MultipartFile interestingStuff) {

    String incomingFilename = interestingStuff.getName();
    String originalFilename = interestingStuff.getOriginalFilename();
    String contentType = interestingStuff.getContentType();

    // do interesting stuff here

    return ok(successfulResponse(new JobData()));
}

The code in the app performing the POST request to thios endpoint looks like

public void loadInvoices(MultipartFile invoices) throws IOException {

    File invoicesFile = new File(invoices.getOriginalFilename());
    invoices.transferTo(invoicesFile);

    LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
    parts.add("file", invoicesFile);


    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);

    String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);

    final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    messageConverters.add(new FormHttpMessageConverter());
    messageConverters.add(new SourceHttpMessageConverter<Source>());

    RestTemplate template = new RestTemplate(messageConverters);

    template.exchange(
            url,
            HttpMethod.POST,
            httpEntity,
            new ParameterizedTypeReference<ArmResponse<JobData>>() {

            });
}

If I post the file in a form using postman - it works The content-type header on the request from Postman looks like

content-type:"multipart/form-data; boundary=--------------------------286899320410555838190774"

When the POST is performed by the RestTemplate I get the following error.

com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input at [Source: (String)""; line: 1, column: 0]

I suspect that the content-type header being sent in the request is wrong. Does anyone know how to correctly set the content-type header for MULTIPART_FORM_DATA?


Solution

  • The solution turned out to be very simple, as usual. Simply call getResource() on the multipartFile.

    public void loadInvoices(MultipartFile invoices) throws IOException {
    
        Resource invoicesResource = invoices.getResource();
    
        LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
        parts.add("file", invoicesResource);
    
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    
        HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
    
        restTemplate.postForEntity("my/url", httpEntity, SommeClass.class);
    }