Search code examples
javavalidationspring-bootfile-uploadthymeleaf

Thymeleaf multiple file input sends empty file when nothing selected


I have a multiple file input in Thymeleaf:

<div class="form-group">
    <label for="photos" class="control-label" th:text="#{projects.new.photos}">Photos</label>
    <input type="file" multiple="multiple" th:field="*{photos}" class="form-control" th:class=" ${#fields.hasErrors('photos')} ? 'form-control is-invalid' : 'form-control'" id="photos" name="photos" placeholder="Project Photos" th:placeholder="#{projects.new.photos.placeholder}">
    <div class="invalid-feedback" th:if="${#fields.hasErrors('photos')}" th:errors="*{photos}"> Error</div>
</div>

in my validator class I'm checking the field like this:

if(files.length == 0 && required==false) {
    return true;
}

The field is not required but when I select no files, I get a file Array with one item in it in my Spring boot application. so the files array in the above snippet has the length of 1 and the validation does not work as expected. the only item in the array has contentType of application/octet-stream and the size is -1. is this the default behavior or I'm doing something wrong?


Solution

  • update:

    I guess I know where this comes from. A input-field of type file doesn't behave like a field of type checkbox. A form submits a key-value-pair, even if the value is not set. Thus, the controller recieves such pair and the single key-nonValue-pair is represented by a empty Multipart-object ("mp1" hereafter). Since you are defining an array of MultipartFile-objects as input-parameter, Spring maps "mp1" to a array with length=1. That's it.

    original answer:

    I guess you are using org.springframework.web.multipart.MultipartFile[] as a input parameter. I think you should check the existence/size by:

    int size = 0;
    for (MultipartFile file : files) 
    {
       if (file != null && !file.isEmpty()) size++;
    }
    

    I'm always doing this null and additional isEmpty check for Multipart objects and I'm thinking the reason was that I sometimes get a MultipartFile object that has no content.

    EDIT: If you are using at least Java 8 you could use this one-liner:

    boolean empty = 
      Arrays.asList(files).stream().filter(f -> !f.isEmpty()).count() == 0;