Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring upload form optional with optional file

We are creating a profile page with a form that optionally has a profile pic on it. We are using Spring 3.2

Here is the form: -

<form:form id="editMember" modelAttribute="memberAjaxEditModel"
    method="POST" class="form-horizontal" enctype="multipart/form-data" >
    ...
    <form:input path="fileData" type="file"/>
    ...
</form>

Here is the controller method: -

@RequestMapping(value = "/{id}", method = RequestMethod.POST)
public String onEditPost(@PathVariable long id, @Valid @ModelAttribute(MemberAjaxEditModel.KEY) MemberAjaxEditModel model, BindingResult result) throws ServiceRecoverableException {
....
}

Here is the Model

public class MemberAjaxEditModel {

...
private CommonsMultipartFile fileData;
...
}

It works fine if a file is submitted on the form, but there are errors in the BindingResult variable if the form is submitted without a file.

Here is the error: -

Field error in object 'memberAjaxEditModel' on field 'fileData': rejected value []; codes [typeMismatch.memberAjaxEditModel.fileData,typeMismatch.fileData,typeMismatch.org.springframework.web.multipart.commons.CommonsMultipartFile,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [memberAjaxEditModel.fileData,fileData]; arguments []; default message [fileData]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.web.multipart.commons.CommonsMultipartFile' for property 'fileData'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.springframework.web.multipart.commons.CommonsMultipartFile] for property 'fileData': no matching editors or conversion strategy found]
like image 248
Ash McConnell Avatar asked Feb 08 '13 11:02

Ash McConnell


2 Answers

It turns out it was the jQuery Form plugin which was sending an empty string instead of what spring expects - nothing to be sent.

I solved the problem using a before submit to remove the fileData value if it wasn't populated like so: -

 function beforeSubmit(arr, $form, options){
     var fileDataIndex = -1;

     $.each(arr, function(index, value) {
          if (value.name == "fileData"){
              if (value.value.length == 0){
                  fileDataIndex = index;
              }
          }
        });

     if (fileDataIndex != -1){
        arr.remove(fileDataIndex);
     }
 }

I hope this helps some googlers with the same problem.

like image 130
Ash McConnell Avatar answered Oct 13 '22 07:10

Ash McConnell


See also github issue 296:

You can use the iframe option to force the same type of post for both cases:

iframe: true

like image 27
Jeroen Wyseur Avatar answered Oct 13 '22 08:10

Jeroen Wyseur