JSF 2.2 h:inputFile & f:validator tag example for file upload & validate

In this tutorial, let us see how to upload files from client to server with the use of JSF h:inputFile tag. Also we will see that how to validate the  file at server side  by writing a  file validator class annotated  with @FacesValidator and with the use of <f:validator> tag in JSF. In my earlier tutorial, we have seen how to upload a file using JSF PrimeFaces.

In this example, let us design a jsf form to accept Name and File to be uploaded

Technologies used in the project

JSF 2.2
Eclipse IDE
Maven 3.3
Java 1.8
servlet 3.0 or above
Tomcat 7.0 or 8.0

Jars related to FileUpload

commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar

Jars Related to JSF

javax.faces.jar (JSF 2.2 (Mojarra 2.2.0))

Project Structure

JSF File Upload structure

Now let us see the steps for uploading file from client to server using JSF h:inputFile tag.

1. Create a Dynamic WebProject in Eclipse (JSFFileUpload)

2. Create web page (JSFFileUpload.xhtml) to accept Name using h:inputText and file using h:inputFile.

The JSF code is given below

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">

<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>JSF File Upload Example</title>
</h:head>
<h:body>
		<h3>JSF 2.2 File Upload Example</h3>
<h:form id="fileUpoad" prependId="false" 	enctype="multipart/form-data">

		<h:outputLabel for="txtIdName" value="Name:" />
		<h:inputText id="txtIdName" value="#{jsfFileUploadBean.name}"/>
		<h:outputLabel for="fu" value="Name:" />
		<h:inputFile id="fu" value="#{jsfFileUploadBean.file}">
			<f:validator validatorId="fileUploadValidator"/>
		</h:inputFile>

		<p> <h:messages id="messages" /></p>

		<h:commandButton value="Upload File" action="#{jsfFileUploadBean.processFileUpload}"></h:commandButton>

</h:form>									

</h:body>
</html> 

The above form’s encryption type should set to “multipart/form-data” that encodes the form data when uploading files. The below JSF tags  are used for file uploading and validation.

<h:inputFile> -to browse and select file from the client machine

<f:validator> – to register a named validator class  (in our example, FileUploadValidator class) instance on the UIComponent associated with the closet UI component tag.

Using the above tags in JSF:


              <h:inputFile id="fu" value="#{jsfFileUploadBean.file}">
                    <f:validator validatorId="fileUploadValidator"/>
             </h:inputFile>

3. Now let us create managed bean for uploading files.

package net.javaonline.jsf.fileupload.controller;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.servlet.http.Part;

import org.apache.commons.io.FilenameUtils;

@ManagedBean(name="jsfFileUploadBean")
@RequestScoped

public class FileUploadBean implements Serializable{

/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	private String name;
	private Part file;

	public Part getFile() {
		return file;
	}

	public void setFile(Part file) {
		this.file = file;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

//Processing of  file uploading.

	public String processFileUpload() throws IOException{

		Part uploadedFile=getFile();

		 final Path destination = Paths.get("c:/temp/"+ FilenameUtils.getName(getSubmittedFileName(uploadedFile)));

		 //When using servlet 3.1
		  //final Path destination = Paths.get("c:/temp/"+ FilenameUtils.getName(uploadedFile.getSubmittedFileName()));

		 InputStream bytes=null;

            if (null!=uploadedFile) {

            	bytes = uploadedFile.getInputStream();  //

		//Copies bytes to destination.
              	  Files.copy(bytes, destination);
            }

        return "success";
	}

	//code to get the submitted file name from the file part header. 

    public static String getSubmittedFileName(Part filePart)
	{
	    String header = filePart.getHeader("content-disposition");
	    if(header == null)
	        return null;
	    for(String headerPart : header.split(";"))
	    {
	        if(headerPart.trim().startsWith("filename"))
	        {
	            return headerPart.substring(headerPart.indexOf('=') + 1).trim().replace("\"", "");
	        }
	    }
	    return null;
	}
}

The above managed bean has two properties named file and name. file property is declared as Part type. Part interface in servlet 3.1 has the method getSubmittedFileName() to get the original file name selected by the client. Lower version of servlet does not have this method. For those using servlet version 3.0 or less, you can use the above getSubmittedFileName(Part filePart) method to get the original file name.

4. Let us create a file validator class (FileUploadValidator) to validate the uploaded file.

The file validator class implements the Validator interface that requires to override the validate(…) method. The class also needs to be annotated with @FacesValidator

package net.javaonline.jsf.fileupload.controller;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.Part;

@FacesValidator(value="fileUploadValidator")
public class FileUploadValidator implements Validator{

	@Override
	public void validate(FacesContext context, UIComponent component, Object value) 	throws ValidatorException {
		Part file = (Part) value;

		FacesMessage message=null;

        try {

        	if (file==null || file.getSize()<=0 || file.getContentType().isEmpty() )
        		message=new FacesMessage("Select a valid file");
        	else if (!file.getContentType().endsWith("pdf"))
        		message=new FacesMessage("Select PDF file");
        	else if (file.getSize()>2000000)
        		 message=new FacesMessage("File size too big. File size allowed  is less than or equal to 2 MB.");

        	if (message!=null && !message.getDetail().isEmpty())
        		{
        			message.setSeverity(FacesMessage.SEVERITY_ERROR);
        			throw new ValidatorException(message );
        		}

        } catch (Exception ex) {
               throw new ValidatorException(new FacesMessage(ex.getMessage()));
        }

	}

}

The above validate method checks the following
i) whether the selected file is valid or not (i.e. should not be null or empty)
ii) the content type should be a PDF
iii) the file size should not be greater than 2 MB.

Please ensure that the validatorId mentioned in the tag <f:validator validatorId=”fileUploadValidator“/>  in JSFFileUpload.xhtml, matches with the value of @FacesValidator annotation(i.e  @FacesValidator(value=”fileUploadValidator“))

5. Create a web page (Ack.xhtml) for file upload acknowledgement

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
    	<title>JSF 2.2 File Upload Acknowledgement </title>
    </h:head>
    <h:body bgcolor="white">

    	<h2>Hi #{jsfFileUploadBean.name} Your File has been Successfully Uploaded to the folder c:\temp</h2>

    </h:body>
</html>

4. web.xml: Map the FacesServlet in web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>JSF_File Upload</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>

</web-app>

6. Create faces-config.xml for providing navigation rule.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">

<application>
	  <resource-bundle>
		<base-name>JSF  File Upload</base-name>
		<var>labels</var>
	   </resource-bundle>
     </application>

    <navigation-rule>
      <from-view-id>JSFFileUpload.xhtml</from-view-id>
     <navigation-case>
		<from-action>#{jsfFileUploadBean.processFileUpload}</from-action>
		<from-outcome>success</from-outcome>
		<to-view-id>Ack.xhtml</to-view-id>
	</navigation-case>
     </navigation-rule>

</faces-config>

Note : Ensure that you have created temp folder under C drive to place the uploaded files.

Run the project by calling the below URL

http://localhost:8080/JSFFileUpload/faces/JSFFileUpload.xhtml

JSF File Upload1

 

When we upload empty file, we get the error “Select a valid file”

JSF File Upload2

 

When we select pdf file having size more than 2 MB, then we will get the below error.

JSF File Upload3

 

When we select any pdf file having less than 2 MB, then the file is successfully uploaded.

JSF File Upload4

Reference: JSF File Upload

 

You may also like

Leave a Reply