Spring Rest Template, создающий многочастную форму / клиент данных, работающий как почтальон, генерирует неконвертируемое исключение - PullRequest
0 голосов
/ 11 октября 2018

Я хочу превратить этого клиента-почтальона с запросом заголовка multipart / form-data в клиент шаблона Spring.

postmanClient

Сейчас у меня естьбазовый контроллер отдыха, который работает хорошо.

@RestController
@RequestMapping("/api")
public class MainConroller {

    private static final Logger log = LoggerFactory.getLogger(MainConroller.class);
    @Autowired
    private MainService mainService;

    public MainConroller(MainService mainService) {
        this.mainService = mainService;
    }

    @PostMapping("/mails/send")
    public void send(
            @RequestParam("usertoken") String usertoken,
            @RequestParam("sendTo") String sendTo,
            @RequestParam("subject") String subject,
            @RequestParam("content") String content,
            @RequestParam(required = false, name = "files") List<MultipartFile> multipartFiles) {
        log.debug("{}, {}, {}, {}", usertoken, sendTo, subject, content);

        mainService.processMessage(usertoken, sendTo, subject, content, multipartFiles);

    }

}

Мне нужно, однако, создать клиент отдыха, поэтому я использовал шаблон отдыха, сейчас он выглядит так:

ArrayList<HttpMessageConverter<?>> converters = new ArrayList<>(
            Arrays.asList(new MappingJackson2HttpMessageConverter(), new ResourceHttpMessageConverter(), new FormHttpMessageConverter()));
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(converters);
    }
    File file = new File("*********");

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

            MultiValueMap<String, Object> fileValueMap = new LinkedMultiValueMap<>();
            fileValueMap.add(file.getName(), file);
            fileValueMap.add(file.getName(), file);
            fileValueMap.add(file.getName(), file);

            HttpEntity<MultiValueMap<String, Object>> filesPart = new HttpEntity<>(fileValueMap, httpHeaders);

    //        String key values part

            MultiValueMap<String, String> stringPart = new LinkedMultiValueMap<>();
            stringPart.add("usertoken", "test");
            stringPart.add("sendTo", "test");
            stringPart.add("subject", "test");
            stringPart.add("content", "test");

            HttpEntity<MultiValueMap<String, String>> objectPart = new HttpEntity<>(stringPart, httpHeaders);


            MultiValueMap<String, Object> multiPartRequest = new LinkedMultiValueMap<>();
            multiPartRequest.add("ObjectPart", objectPart);
            multiPartRequest.add("FilesPart", filesPart);


            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multiPartRequest, httpHeaders);

            String serverUrl = "****";

            restTemplate().postForEntity(serverUrl, requestEntity, String.class);

Проблема в том, что когда я пытаюсь отправить запрос, он выдает

Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [multipart/form-data]

Обновление

Решение на стороне клиента очень простое, вы можете просто отправитьСтроковые значения в значениях объекта, которые будут автоматически преобразованы в строки через универсальные шаблоны.

Кроме того, файлы нельзя отправлять только в виде файлов, но вместо этого необходимо создать FileSystemResource, вот полный кодсторона клиента:

@Service
public class RestTemplatePost {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public void prepareMessage() throws Exception {


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

        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
        form.add("usertoken", "test");
        form.add("sendTo", "test");
        form.add("subject", "test");
        form.add("content", "test");
        form.add("files", getTestFile());
        form.add("files", getTestFile());

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, httpHeaders);

        String serverUrl = "******";

        restTemplate().postForEntity(serverUrl, requestEntity, String.class);


    }

    public static Resource getTestFile() throws IOException {
    Path testFile = Paths.get("C****");
    System.out.println("Creating and Uploading Test File: " + testFile);
    Files.write(testFile, "Hello World !!, This is a test file.".getBytes());
    return new FileSystemResource(testFile.toFile());
}

}

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Вы делаете вещи слишком сложными.Вы должны использовать одну карту для хранения значений формы, а не карту карт.Рядом с этим Spring Boot уже есть RestTemplate, поэтому вам не нужно снова настраивать свой собственный.

File file = new File("*********");

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

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

form.add("usertoken", "test");
form.add("sendTo", "test");
form.add("subject", "test");
form.add("content", "test");

HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, httpHeaders);

String serverUrl = "****";

restTemplate().postForEntity(serverUrl, requestEntity, String.class);

RestTemplate (или фактически FormHttpMessageConverter) преобразует его в правильный запрос.

0 голосов
/ 11 октября 2018

Конструктор RestTemplate по умолчанию не включает конвертеры сообщений, его нужно добавить.Например, вы можете сделать это следующим образом:

HttpEntity<MultiValueMap<String, Object>> requestEntity = new 
HttpEntity<MultiValueMap<String, Object>>(parts, requestHeaders);

RestTemplate restTemplate = getRestTemplate();
restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

return restTemplate.postForObject(apiURI, requestEntity, String.class);
...