«1. Обзор

В этом кратком руководстве основное внимание уделяется тому, как загрузить составной файл с помощью RestTemplate Spring.

Мы увидим как один файл, так и несколько файлов — загружайте их с помощью RestTemplate.

2. Что такое составной HTTP-запрос?

Проще говоря, базовое тело запроса HTTP POST содержит данные формы в парах имя/значение.

С другой стороны, HTTP-клиенты могут создавать составные HTTP-запросы для отправки текстовых или двоичных файлов на сервер; он в основном используется для загрузки файлов.

Другим распространенным вариантом использования является отправка электронного письма с вложением. Запросы файлов, состоящих из нескольких частей, разбивают большой файл на более мелкие фрагменты и используют граничные маркеры для обозначения начала и конца блока.

Узнайте больше о составных запросах здесь.

3. Зависимость Maven

Одной этой зависимости достаточно для клиентского приложения:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>

4. Сервер загрузки файлов

API файлового сервера предоставляет две конечные точки REST для загрузки одного и нескольких файлов соответственно. :

    POST /fileserver/singlefileupload/ POST /fileserver/multiplefileupload/

5. Загрузка одного файла

Сначала рассмотрим загрузку одного файла с помощью RestTemplate.

Нам нужно создать HttpEntity с заголовком и телом. Задайте для заголовка типа содержимого значение MediaType.MULTIPART_FORM_DATA. Когда этот заголовок установлен, RestTemplate автоматически упорядочивает данные файла вместе с некоторыми метаданными.

Метаданные включают имя файла, размер файла и тип содержимого файла (например, текстовый/обычный):

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

Затем создайте тело запроса как экземпляр класса LinkedMultiValueMap. LinkedMultiValueMap является оболочкой LinkedHashMap, хранящей несколько значений для каждого ключа в LinkedList.

В нашем примере метод getTestFile() создает фиктивный файл на лету и возвращает FileSystemResource:

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

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

Обратите внимание, что загрузка одного файла указывает на конечную точку /fileserver/singlefileupload/.

В конце вызов restTemplate.postForEntity() завершает работу по соединению с заданным URL и отправке файла на сервер:

HttpEntity<MultiValueMap<String, Object>> requestEntity
 = new HttpEntity<>(body, headers);

String serverUrl = "http://localhost:8082/spring-rest/fileserver/singlefileupload/";

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
  .postForEntity(serverUrl, requestEntity, String.class);

6. Загрузка нескольких файлов

При загрузке нескольких файлов единственное отличие от загрузки одного файла заключается в построении тела запроса.

Давайте создадим несколько файлов и добавим их с одним и тем же ключом в MultiValueMap.

Очевидно, URL-адрес запроса должен ссылаться на конечную точку для загрузки нескольких файлов:

MultiValueMap<String, Object> body
  = new LinkedMultiValueMap<>();
body.add("files", getTestFile());
body.add("files", getTestFile());
body.add("files", getTestFile());
    
HttpEntity<MultiValueMap<String, Object>> requestEntity
  = new HttpEntity<>(body, headers);

String serverUrl = "http://localhost:8082/spring-rest/fileserver/multiplefileupload/";

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
  .postForEntity(serverUrl, requestEntity, String.class);

Всегда можно смоделировать загрузку одного файла, используя загрузку нескольких файлов.

7. Заключение

В заключение мы увидели случай переноса MultipartFile с использованием Spring RestTemplate.

Как всегда, пример исходного кода клиента и сервера доступен на GitHub.