Используйте Jquery и FormData для отправки полей формы и загрузки файла в контроллер Spring MVC в приложении Spring Boot.

Я не могу использовать Jquery и FormData для отправки полей формы и загрузки файла в контроллер Spring MVC в приложении Spring Boot.

Я продолжаю получать это исключение «Текущий запрос не является составным запросом» на стороне контроллера.

Моя установка.

У меня есть обычное веб-приложение Spring Boot

Это моя весенняя загрузочная версия:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.7.RELEASE</version>
</parent>

Моя отправка формы Ajax выглядит так:

var entityJson = form2js("my-form-id",null,false); // js library to get json from form
var entityJsonStr = JSON.stringify(entityJson);

var formData = new FormData();
formData.append("data", entityJsonStr); // the entered data as JSON


// append files, if there are any
$.each($("#my-form-id").find("input[type='file']"), function(i, tag) {
    $.each($(tag)[0].files, function(i, file) {
       formData.append(tag.name, file);
    });
});

$.ajax({
    url:     theUrl,
    type:    'POST',
    headers: {'Content-Type': undefined},
    cache: false,
    processData: false,
    data:    formData,
    error: function(xhr,status,err){
        // failure handling
    },
    success: function(response){
        // success handling
    }
});

Только представление json работает абсолютно нормально (когда я отправляю только entityJsonStr вместо экземпляра FormData)

На стороне сервера мой контроллер выглядит так:

@RequestMapping(value="/save", method= RequestMethod.POST, produces=APPLICATION_JSON_UTF_8)
public @ResponseBody WebResponse<MyEntity> save(
        @Valid @RequestPart(value="data") MyEntity myEntity
        ,@RequestPart(value = "image", required = false) MultipartFile image
) throws Exception {
    try {

        validateImage(image);
        saveImage(myEntity.getName() + ".jpg", image);

        shoppingCenterService.save(myEntity);
        MyEntity shoppingCenterWithOnlyId = getEmptyShoppingCenterWithId(myEntity.getId());

        return new WebResponse(true, SHOPPINGCENTER_SAVE_SUCCESS);
    } catch (DuplicacyException de) {
        return getDuplicacyResponse(de, myEntity);
    } catch(Exception e) {
        LOGGER.error("MyEntity Controller[save]", e);
        return new WebResponse(false, MYENTITY_SAVE_FAILED); // custom response
    }
}

когда я не использую @RequestPart, а просто использую @Valid @RequestBody MyEntity myEntity и не использую объект FormData в javascript, я получаю правильный json, который преобразуется в объект MyEntity...

Я продолжаю получать это исключение:

org.springframework.web.multipart.MultipartException: The current request is not a multipart request   

Я пробовал все следующие комбинации, ничего не работает

// dataType: 'json',
// contentType: 'application/json',

headers: {'Content-Type': undefined},
cache: false,
//  contentType: null,
//  processData: false,
// enctype: 'multipart/form-data',
processData: false,
//contentType: false,
//cache: false,

// async:   true,
// cache:   false,
// global:  false,

но ничто не отправляет файл formdata + правильно.

Я пытаюсь заставить это работать уже пару дней... Я не вижу, что я делаю неправильно.

Если у кого-то это работает, поделитесь решением.

Обновление:

После ответа Jny я попытался

headers: {'Content-Type': 'multipart/form-data'}

и

contentType:  'multipart/form-data'

Теперь я понимаю :(

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

Моя полезная нагрузка запроса выглядит так:

------WebKitFormBoundaryPG92Ng6h630YkJKN
Content-Disposition: form-data; name="form_data"

{"id":"","name":"s","code":"s" 
  // ... more json
}
------WebKitFormBoundaryPG92Ng6h630YkJKN
Content-Disposition: form-data; name="image"; filename="ThumbsUp.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryPG92Ng6h630YkJKN--

person R K Punjal    schedule 23.11.2015    source источник
comment
** Обратите внимание, что WebResponse — это мой собственный класс ответов.   -  person R K Punjal    schedule 23.11.2015
comment
Вы получаете сообщение об ошибке, что ваш запрос не является составным запросом... Как вы думаете, что это значит? Может быть, вам нужно изменить заголовок вашего контента?   -  person jny    schedule 23.11.2015
comment
Я пробовал с заголовками: {'Content-Type': 'multipart/form-data'} и contentType: 'multipart/form-data' Теперь я получаю :( FileUploadException: запрос был отклонен, так как не найдена составная граница My Request Payload выглядит так: ------ WebKitFormBoundaryPG92Ng6h630YkJKN Content-Disposition: form-data; Расположение: form-data; name=image; filename=ThumbsUp.jpg Content-Type: image/jpeg ------WebKitFormBoundaryPG92Ng6h630YkJKN--   -  person R K Punjal    schedule 23.11.2015


Ответы (1)


Решение найдено!! и это работает теперь Yippee :)

Что нам нужно сделать, так это когда мы устанавливаем строку Json в FormData, нам нужно указать тип содержимого, что эта часть является json .... поэтому решение теперь выглядит так:

var entityJson = form2js("my-form-id",null,false); // js library to get json from form
var entityJsonStr = JSON.stringify(entityJson);

var formData = new FormData();
formData.append("data", new Blob([entityJsonStr], {
                type : "application/json"  // ** specify that this is JSON**
            })); 


// append files, if there are any
$.each($("#my-form-id").find("input[type='file']"), function(i, tag) {
    $.each($(tag)[0].files, function(i, file) {
       formData.append(tag.name, file);
    });
});

$.ajax({
    url:     theUrl,
    type:    'POST',
    processData: false,
    contentType: false,
    cache: false,
    data:    formData,
    error: function(xhr,status,err){
        // failure handling
    },
    success: function(response){
        // success handling
    }
});

и тогда контроллер выглядит так же, как и раньше.

Было еще одно изменение, которое я в итоге сделал для своей сущности. Поскольку теперь у меня есть это новое поле формы как «изображение», которое не должно было быть свойством непосредственно в моем объекте.

Поэтому я попросил Джексона игнорировать эти ненанесенные на карту свойства.

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
// MyEntity class goes here {}

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

person R K Punjal    schedule 24.11.2015
comment
Я получаю эту ошибку в приведенной выше реализации: сервер не может или не будет обрабатывать запрос из-за чего-то, что воспринимается как ошибка клиента (например, неверный синтаксис запроса, недопустимый кадр сообщения запроса или вводящая в заблуждение маршрутизация запроса). ‹/ p›‹hr class=line /›‹h3›Apache Tomcat/9.0.4‹/h3›‹/body›‹/html› - person oOXAam; 29.06.2020