Class InputFile

  • All Implemented Interfaces:
    ClientBehaviorHolder, EditableValueHolder, PartialStateHolder, StateHolder, TransientStateHolder, ValueHolder, ComponentSystemEventListener, FacesListener, SystemEventListenerHolder, EventListener

    public class InputFile
    extends HtmlInputFile

    The <o:inputFile> is a component that extends the standard <h:inputFile> and adds support for multiple, directory, accept and maxsize attributes, along with built-in server side validation on accept and maxsize attributes. Additionally, it makes sure that the value of HTML file input element is never rendered. The standard <h:inputFile> renders Part#toString() to it which is unnecessary.

    Usage

    You can use it the same way as <h:inputFile>, you only need to change h: into o: to get the extra support for multiple, directory and accept attributes. Here's are some usage examples.

    Single file selection

    It is basically not different from <h:inputFile>. You might as good use it instead.

     <h:form enctype="multipart/form-data">
         <o:inputFile value="#{bean.file}" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
     </h:form>
     
     private Part file; // +getter+setter
    
     public void upload() {
         if (file != null) {
             String name = Servlets.getSubmittedFileName(file);
             String type = file.getContentType();
             long size = file.getSize();
             InputStream content = file.getInputStream();
             // ...
         }
     }
     

    Note that it's strongly recommended to use Servlets.getSubmittedFileName(Part) to obtain the submitted file name to make sure that any path is stripped off. Some browsers are known to incorrectly include the client side path or even a fake path along with the file name.

    Multiple file selection

    The multiple attribute can be set to true to enable multiple file selection. With this setting the enduser can use control/command/shift keys to select multiple files.

     <h:form enctype="multipart/form-data">
         <o:inputFile value="#{bean.files}" multiple="true" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
     </h:form>
     
     private List<Part> files; // +getter+setter
    
     public void upload() {
         if (files != null) {
             for (var file : files) {
                 var name = Servlets.getSubmittedFileName(file);
                 var type = file.getContentType();
                 var size = file.getSize();
                 var content = file.getInputStream();
                 // ...
             }
         }
     }
     

    Folder selection

    The directory attribute can be set to true to enable folder selection. This implicitly also sets multiple attribute to true and renders an additional webkitdirectory attribute to HTML for better browser compatibility.

     <h:form enctype="multipart/form-data">
         <o:inputFile value="#{bean.files}" directory="true" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
     </h:form>
     
     private List<Part> files; // +getter+setter
    
     public void upload() {
         if (files != null) {
             for (var file : files) {
                 var name = Servlets.getSubmittedFileName(file);
                 var type = file.getContentType();
                 var size = file.getSize();
                 var content = file.getInputStream();
                 // ...
             }
         }
     }
     

    Do note that this does not send physical folders, but only files contained in those folders.

    Media type filtering

    The accept attribute can be set with a comma separated string of media types of files to filter in browse dialog. An overview of all registered media types can be found at IANA.

     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.losslessImageFile}" accept="image/png,image/gif" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message for="file" />
     </h:form>
     
     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.anyImageFile}" accept="image/*" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message for="file" />
     </h:form>
     
     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.anyMediaFile}" accept="audio/*,image/*,video/*" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message for="file" />
     </h:form>
     

    This will also be validated in the server side using a built-in validator. Do note that the accept attribute only filters in client side and validates in server side based on the file extension, and this does thus not strictly validate the file's actual content. To cover that as well, you should in the bean's action method parse the file's actual content using the tool suited for the specific media type, such as ImageIO#read() for image files, and then checking if it returns the expected result.

    The default message for server side validation of accept attribute is:

    {0}: Media type of file ''{1}'' does not match ''{2}''

    Where {0} is the component's label and {1} is the submitted file name and {2} is the value of accept attribute.

    You can override the default message by the acceptMessage attribute:

     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.anyImageFile}" accept="image/*" acceptMessage="File {1} is unacceptable!" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message for="file" />
     </h:form>
     

    Or by the custom message bundle file as identified by <application><message-bundle> in faces-config.xml. The message key is org.omnifaces.component.input.InputFile.accept.

     org.omnifaces.component.input.InputFile.accept = File {1} is unacceptable!
     

    File size validation

    The maxsize attribute can be set with the maximum file size in bytes which will be validated on each selected file in the client side if the client supports HTML5 File API. This validation will be performed by custom JavaScript in client side instead of by Faces in server side. This only requires that there is a <h:message> or <h:messages> component and that it has its id set.

     <o:inputFile id="file" ... />
     <h:message id="messageForFile" for="file" /> <!-- This must have 'id' attribute set! -->
     

    This way the client side can trigger Faces via an ajax request to update the message component with the client side validation message. Noted should be that the file(s) will not be sent, hereby saving network bandwidth.

     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.file}" maxsize="#{10 * 1024 * 1024}" /> <!-- 10MiB -->
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message id="messageForFile" for="file" />
     </h:form>
     

    This will also be validated in the server side using a built-in validator.

    The default message for both client side and server side validation of maxsize attribute is:

    {0}: Size of file ''{1}'' is larger than maximum of {2}

    Where {0} is the component's label and {1} is the submitted file name and {2} is the value of maxsize attribute.

    You can override the default message by the maxsizeMessage attribute:

     <h:form enctype="multipart/form-data">
         <o:inputFile id="file" value="#{bean.file}" maxsize="#{10 * 1024 * 1024}" maxsizeMessage="File {1} is too big!" />
         <h:commandButton value="Upload" action="#{bean.upload}" />
         <h:message id="messageForFile" for="file" />
     </h:form>
     

    Or by the custom message bundle file as identified by <application><message-bundle> in faces-config.xml. The message key is org.omnifaces.component.input.InputFile.maxsize.

     org.omnifaces.component.input.InputFile.maxsize = File {1} is too big!
     
    Since:
    2.5
    Author:
    Bauke Scholtz
    • Field Detail

      • COMPONENT_TYPE

        public static final String COMPONENT_TYPE
        The component type, which is "org.omnifaces.component.input.InputFile".
        See Also:
        Constant Field Values
    • Constructor Detail

      • InputFile

        public InputFile()
        The constructor instructs Faces to register all scripts during the render response phase if necessary.
    • Method Detail

      • decode

        public void decode​(FacesContext context)
        This override checks if client side validation on maxsize has failed and if multi file upload is enabled. If client side validation on maxsize has failed, then it will render the message. If multi file upload is enabled, then it will set all parts as submitted value instead of only the last part as done in h:inputFile.
        Overrides:
        decode in class UIInput
      • getConvertedValue

        protected Object getConvertedValue​(FacesContext context,
                                           Object submittedValue)
        This override will convert the individual parts if multi file upload is enabled and collect only non-null parts having a non-empty file name and a file size above zero.
        Overrides:
        getConvertedValue in class UIInput
      • validateValue

        protected void validateValue​(FacesContext context,
                                     Object convertedValue)
        This override will server-side validate any accept and maxsize for each part.
        Overrides:
        validateValue in class UIInput
      • getValue

        public Object getValue()
        This override returns null during render response as it doesn't make sense to render Part#toString() as value of file input, moreover it's for HTML security reasons discouraged to prefill the value of a file input even though browsers will ignore it.
        Specified by:
        getValue in interface ValueHolder
        Overrides:
        getValue in class UIInput
      • validateHierarchy

        protected void validateHierarchy​(FacesContext context)
        Validate the component hierarchy. This should only be called when project stage is Development.
        Throws:
        IllegalStateException - When component hierarchy is wrong.
      • isMultiple

        public boolean isMultiple()
        Returns whether or not to allow multiple file selection. This implicitly defaults to true when directory attribute is true.
        Returns:
        Whether or not to allow multiple file selection.
      • setMultiple

        public void setMultiple​(boolean multiple)
        Sets whether or not to allow multiple file selection.
        Parameters:
        multiple - Whether or not to allow multiple file selection.
      • isDirectory

        public boolean isDirectory()
        Returns whether or not to enable directory selection.
        Returns:
        Whether or not to enable directory selection.
      • setDirectory

        public void setDirectory​(boolean directory)
        Sets whether or not to enable directory selection. When true, this implicitly defaults the multiple attribute to true.
        Parameters:
        directory - Whether or not to enable directory selection.
      • getAccept

        public String getAccept()
        Returns comma separated string of mime types of files to filter in client side file browse dialog. This is also validated in server side.
        Returns:
        Comma separated string of mime types of files to filter in client side file browse dialog.
      • setAccept

        public void setAccept​(String accept)
        Sets comma separated string of media types of files to filter in client side file browse dialog.
        Parameters:
        accept - Comma separated string of mime types of files to filter in client side file browse dialog.
      • getAcceptMessage

        public String getAcceptMessage()
        Returns validation message to be displayed when the condition in accept attribute is violated.
        Returns:
        Validation message to be displayed when the condition in accept attribute is violated.
      • setAcceptMessage

        public void setAcceptMessage​(String acceptMessage)
        Sets validation message to be displayed when the condition in accept attribute is violated.
        Parameters:
        acceptMessage - Validation message to be displayed when the condition in accept attribute is violated.
      • getMaxsize

        public Long getMaxsize()
        Returns maximum size in bytes for each selected file. This is validated in both client and server side.
        Returns:
        Maximum size in bytes for each selected file.
      • setMaxsize

        public void setMaxsize​(Long maxsize)
        Sets maximum size in bytes for each selected file.
        Parameters:
        maxsize - Maximum size in bytes for each selected file.
      • getMaxsizeMessage

        public String getMaxsizeMessage()
        Returns validation message to be displayed when the condition in maxsize attribute is violated.
        Returns:
        Validation message to be displayed when the condition in maxsize attribute is violated.
      • setMaxsizeMessage

        public void setMaxsizeMessage​(String maxsizeMessage)
        Sets validation message to be displayed when the condition in maxsize attribute is violated.
        Parameters:
        maxsizeMessage - Validation message to be displayed when the condition in maxsize attribute is violated.