Как исправить multipart / form-data MediaType, не установленный с помощью Jackson Spring MVC - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь отправить изображение продукта и продукта из внешнего интерфейса Angular 7 в бэкэнд SpringMVC. Чтобы добавить поддержку файлов Multipart, я добавил этот bean-компонент в свой AppConfig.

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(1000000);
    return multipartResolver;
}

Так как я хочу получить объект Product отдельно внутри контроллера, я использую @RequestPart для извлечения обоих по отдельности, например:

@RequestMapping(value = "save", method = RequestMethod.POST)
public ResponseEntity addProduct(@Valid @RequestPart Product product, @RequestPart MultipartFile[] images, BindingResult bindingResult, HttpServletRequest 
}

На веб-интерфейсе я добавляю изображение в FormData следующим образом:

let formData = new FormData();

formData.append('product', new Blob([JSON.stringify(this.product)],{ type: "application/json" }));
// I iterate and append all the images like this
formData.append('image[]', this.images, this.images.name);

this.http.post(this.appService.getApiUrl() + "api/product/save/", product);

Проблема в том, что всякий раз, когда я отправляю форму, я получаю это исключение в качестве ответа: HTTP Status 415 - Неподдерживаемый тип носителя . Я попытался отладить эту проблему, установив точки останова внутри класса CommonsMultipartResolver и после отслеживания запроса по коду. Я обнаружил, что при вызове getSupportedMediaTypes () он возвращает только два типа мультимедиа:

  1. применение / JSON
  2. Применение / * + * 1021 JSON *

Внутри следующего метода в AbstractHttpMessageConverter :

protected boolean canRead(@Nullable MediaType mediaType) {
    if (mediaType == null) {
        return true;
    } else {
        Iterator var2 = this.getSupportedMediaTypes().iterator();

        MediaType supportedMediaType;
        do {
            if (!var2.hasNext()) {
                return false;
            }

            supportedMediaType = (MediaType)var2.next();
        } while(!supportedMediaType.includes(mediaType));
            return true;
    }
}

Найдя это, я попытался добавить MediaType.MULTIPART_FORM_DATA вот так внутри AppConfig:

@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    for (HttpMessageConverter converter : converters) {
        if (converter instanceof MappingJackson2HttpMessageConverter) {
            List<MediaType> types = new ArrayList<>();
            types.add(MediaType.APPLICATION_JSON);
            types.add(MediaType.APPLICATION_JSON_UTF8);
            types.add(MediaType.MULTIPART_FORM_DATA);
            ((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(types);

            Hibernate5Module hibernate5Module = new Hibernate5Module();
       hibernate5Module.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);

            ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
            mapper.registerModule(hibernate5Module);
        }
    }
}

Но это все равно не сработает. Когда приложение запускается, я вижу конструктор AbstractJackson2HttpMessageConverter , вызываемый с помощью моих MediaTypes , но после него они перезаписываются большим количеством обращений к одному и тому же конструктору. Можно ли как-то сохранить MediaType для сохранения? Возможно, я смотрю не в ту сторону, поэтому любое понимание будет полезным.

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

Библиотека Джексона требуется на пути к классам. Spring не объявляет это по умолчанию. Убедитесь, что по крайней мере com.fasterxml.jackson.core:jackson-databind доступно в пути к классам приложения Spring MVC. Пример для Apache Maven:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>${jackson.version}</version> 
</dependency>

Пример значения jackson.version: 2,9,0

0 голосов
/ 27 марта 2019

1) Вам необходимо указать поддерживаемые входные данные на стороне сервера.Поскольку вы отправляете файл, это означает, что сервер использует многочастные данные.Для multipart нам нужно установить потребляет = "multipart / form-data"

@RequestMapping(value = "save", method = RequestMethod.POST, consumes = "multipart/form-data")
public ResponseEntity addProduct(@Valid @RequestPart Product product, @RequestPart MultipartFile[] images, BindingResult bindingResult, HttpServletRequest 
}

2) Так как форма отправляет многокомпонентные данные, нам нужно сначала указать тип содержимогоконец также в заголовке http в пост-вызове. content-type: multipart / form-data "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...