Search code examples
javaspring-bootmultipartform-dataresttemplate

How to send a multipart file to a service from another service


I have two endpoints api which are /uploadand /redirect

/upload is where I directly upload the file. /redirect is where i receive the file and pass it to upload and get the JSON response from /upload.So below is my code:

package com.example;

import java.io.BufferedOutputStream;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class UserLogsController {

    @Autowired
    @Qualifier("restTemplateUserRegitration")
    private RestTemplate restTemplateUserRegitration;

    @Bean
    public RestTemplate restTemplateUserRegitration() {

        RestTemplateBuilder builderUserRegitration = new RestTemplateBuilder();
        RestTemplate buildUserRegitration = builderUserRegitration.build();

        return buildUserRegitration;
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public @ResponseBody ResponseEntity<Map<String, Object>> handleFileUpload(
            @RequestParam("file") MultipartFile file) {
        String name = file.getName();
        System.out.println(name);
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                BufferedOutputStream stream = new BufferedOutputStream(
                        new FileOutputStream(new File("D:\\myfile.csv")));
                stream.write(bytes);
                stream.close();

                JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                FeedBackResponse.setCode(100);
                FeedBackResponse.setMessage("Successfully Updated Batch User List");
                Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                FeedBackStatus.put("status", FeedBackResponse);
                return ResponseEntity.ok(FeedBackStatus);

            } catch (Exception e) {
                JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                FeedBackResponse.setCode(100);
                FeedBackResponse.setMessage(e.getMessage());
                Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                FeedBackStatus.put("status", FeedBackResponse);
                return ResponseEntity.ok(FeedBackStatus);
            }
        } else {
            JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
            FeedBackResponse.setCode(100);
            FeedBackResponse.setMessage("Successfully Updated Batch User List");
            Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
            FeedBackStatus.put("status", FeedBackResponse);
            return ResponseEntity.ok(FeedBackStatus);
        }
    }

    @RequestMapping(value = "/redirect", produces = { MediaType.APPLICATION_JSON_VALUE }, method = RequestMethod.POST)
    public ResponseEntity<?> registerBatchUser(@RequestParam("file") MultipartFile file) {

        Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
        FeedBackStatus = restTemplateUserRegitration.postForObject("http://localhost:8080/upload", file, Map.class);
        return ResponseEntity.ok(FeedBackStatus);

    }

}

The endpoint /upload works pretty much fine.But when i call /redirect it throws an error of

"exception": "org.springframework.http.converter.HttpMessageNotWritableException", "message": "Could not write JSON document: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])",

I am not sure why is this occuring.Any help is appreciated.


Solution

  • This made the trick

    @RequestMapping(value = "/redirect", produces = { MediaType.APPLICATION_JSON_VALUE }, method = RequestMethod.POST)
        public ResponseEntity<?> registerBatchUser(@RequestParam("file") MultipartFile file) {
           if (!file.isEmpty()) {
                try {
                    byte[] bytes = file.getBytes();
                    BufferedOutputStream stream = new BufferedOutputStream(
                            new FileOutputStream(new File("D:\\myfileredirect.csv")));
                    stream.write(bytes);
                    stream.close();
    
    
                } catch (Exception e) {
                    JwtAuthenticationErrorResponse FeedBackResponse = new JwtAuthenticationErrorResponse();
                    FeedBackResponse.setCode(100);
                    FeedBackResponse.setMessage(e.getMessage());
                    Map<String, Object> FeedBackStatus = new HashMap<String, Object>();
                    FeedBackStatus.put("status", FeedBackResponse);
                    return ResponseEntity.ok(FeedBackStatus);
                }
            MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
            parameters.add("file", new FileSystemResource("D:\\myfileredirect.csv")); 
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "multipart/form-data");
    
    
    
            Map<String, Object> FeedBackStatus=new HashMap<String, Object>();
            FeedBackStatus =  restTemplateUserRegitration.exchange("http://localhost:8080/upload",  HttpMethod.POST,  new HttpEntity<MultiValueMap<String, Object>>(parameters, headers), Map.class).getBody();
            return ResponseEntity.ok(FeedBackStatus);
    
        }
    

    So what I did was basically collected the file rewrite it and then conver to a MultiValueMap and send to the service.