Каков наилучший способ передачи файлов вместе с json

#spring #spring-boot #spring-restcontroller

Вопрос:

1. Контекст

Клиенту необходимо отправить запрос на ОТДЫХ, чтобы данные формы могли храниться на сервере. Вот пример формы, которую необходимо отправить:

1

Также имейте в виду, что компонент dropzone будет изменен таким образом, чтобы он также запрашивал необязательное небольшое описание для каждого файла, который пользователь будет загружать.

Таким образом, в этом примере сервер получит:

  • UseCase (строка)
  • Файлы : Один или несколько файлов
    • Описание

Сервер настроен с помощью Spring-Boot, @RestController, и библиотека Jakson обрабатывает сериализацию/десериализацию.

2. Требования

Операция должна быть атомарной

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

Файл должен быть напрямую связан с соответствующим описанием

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

Держите количество параметров в контроллере как можно меньшим

For the purpose of this post I have simplified the examples. But in reality the form will send way more data than a string and some files.
For that reason I’d like that the signature of the function stays as simple as possible.

3. Question

I have checked the documentation, many tutorials and there are many possibilities to implement this but they are often a bit off considering my 3 requirements.

Considering that, what would be the best way to handle this according to you?
Please give me an example of how :

  1. You would write the controller’s signature.
  2. You would format the front-end data (For instance what ‘Content-Type’ header should I use).

Here is an example of the controller I’m using (don’t mind the attempt I’ve done).

 @PostMapping(path = "/form/{formId}/data", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public void postData(@PathVariable Long formId, @Valid @ModelAttribute NewFormData formData) throws IOException {
    //Do some stuff like calling the form's service to process the request
}
 

As you can see I’m trying to make Spring deserialize the received data in a NewFormData object. That way it makes it easier to work with the many data sent by the form.

Here is a example of the class I used as the parameter of the controller that will contain the form’s data:

 public class NewFormData {
    /*
     * Form's data that will be deseriliazed
     */
    NewTextBoxData textBoxData;
    List<NewFileData> fileData;

    private static class NewData {
        /**
         * If a PUT request is sent later I will have to modified the existing data in DB. This value will either be an int or null if it's not persisted yet.
         */
        public Integer Id;
    }

    public static class NewTextBoxData extends NewData{
        public String value;
    }
    public static class NewFileData extends NewData{
        public String description;
        public MultipartFile file;
    }
}