Search code examples
servletsfile-uploadis-empty

Why does Servlet think my empty HTML file element has a file in it?


I am using a Java Servlet to handle an html form and it includes a file input element:

<input type="file" id="fileUpload" name="file" multiple />

I used the example code in this excellent answer to process multiple files at once. The code I'm using is:

List<Part> fileParts = req.getParts().stream().filter(part -> "file".equals(part.getName())).collect(Collectors.toList()); // Retrieves <input type="file" name="file" multiple="true">
for (Part filePart : fileParts) {
            String fileName = filePart.getSubmittedFileName();
            InputStream fileContent = filePart.getInputStream();
            // Do stuff here
}

This code works great. My problem is, when I don't attach anything, my code still thinks fileParts has a Part object in it. Doing some debugging, the Part object does seem to be there, but of course there is no InputStream or SubmittedFileName to get, since I didn't upload any files. Why is this? I am new to lambda functions and collections, but it seems like this "fileParts" Collection should be empty when I don't select any files for upload.


Solution

  • This is just how HTML works.

    The same is true for non-file inputs. When an empty input is submitted, you get an empty value, not null. The difference is significant. A value of null represents absence of the input field. This is particularly useful when the form has multiple submit buttons and you'd like to distinguish the button pressed.

    Given a <input type="text" name="foo">,

    String foo = request.getParameter("foo");
    
    if (foo == null) {
        // foo was not submitted at all.
    } else if (foo.isEmpty()) {
        // foo is submitted without value.
    } else {
        // foo is submitted with a value.
    }
    

    And a <input type="file" name="bar">,

    Part bar = request.getPart("bar");
    
    if (bar == null) {
        // bar was not submitted at all.
    } else if (bar.getSize() == 0) {
        // bar is submitted without value.
    } else {
        // bar is submitted with a value.
    }