JSF Primefaces Multiple file upload dynamically with/ without Ajax.

In this tutorial, we will see how to upload multiple files dynamically with the use of datatable and fileUpload tag without using multiple=”true” property. JSF Primefaces has the inbuilt facility to upload multiple files in advanced mode. Just we need add the attribute multiple=”true” in the <p:fileUpload/> tag as given below. You can also visit my earlier post on JSF Primefaces file upload example.

<h:form>
 <p:fileUpload fileUploadListener="#{fileUploadView.handleFileUpload}" mode="advanced" dragDropSupport="false"
multiple="true" update="messages" sizeLimit="100000" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
<p:growl id="messages" showDetail="true" />
</h:form>

 

But this will not serve our purpose at all times. Consider the following situation. Suppose an user has to upload many files along with other related information. For example, when you apply for a job, you may need to upload various mark sheets/ certificates such as 10th, 10+2, Degree, PG and certificate courses. In this situation, you may need to add/remove one or more certificates dynamically along with other related details. In this scenario, the above fileupload technique may not be helpful.

                In this example, initially two rows will be displayed to accept 10th and 12th certificates which are not removable. Then you can add more documents by adding rows dynamically which can also be removed later. You can set non-removable documents by setting the flag removable to false.  Now let us design a form to accept name, institute name and upload certificates/ Mark sheets. We will do this in two ways.

1. Using p:fileUpload with advanced mode

In advanced mode, each document is uploaded individually.

2. Using p:fileUpload with simple mode

Here in simple mode, we will select multiple documents first then upload all the  files at one go by clicking on the submit button.

Technology used in the project:

JSF 2.2

Primefaces 5.2

servlet 3

Eclipse

JBoss EAP 6.1+

Additional Jars used:

commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
javax.faces-2.2.11.jar
primefaces-5.2.jar
servlet 3.1.0.jar

Project Structure:
JSF Primefaces multiple file upload

 

Now let see the complete code:

Method I) Using p:fileUpload with advanced mode:
In this method, each document is uploaded individually by clicking on the upload button. More documents can be added dynamically

1. Create Document Upload Model  (DocumentModel.java)  to capture document related information such as document name, institute name, etc..

package net.javaonline.jsf.primefaces.multiplefileupload.controller;

import java.io.Serializable;

public class DocumentModel implements Serializable {
	int srNo;
	String documentName;
	String institute;

	boolean removable = Boolean.TRUE; // to mention whether the document can be
										// removed or not
	boolean uploaded = Boolean.FALSE; // flag to mention file uploaded status
	private String documentUploadedPath;// to capture uploaded path

	public boolean isRemovable() {
		return removable;
	}

	public void setRemovable(boolean removable) {
		this.removable = removable;
	}

	public String getInstitute() {
		return institute;
	}

	public void setInstitute(String institute) {
		this.institute = institute;
	}

	public String getDocumentUploadedPath() {
		return documentUploadedPath;
	}

	public void setDocumentUploadedPath(String documentUploadedPath) {
		this.documentUploadedPath = documentUploadedPath;
	}

	public boolean isUploaded() {
		return uploaded;
	}

	public void setUploaded(boolean uploaded) {
		this.uploaded = uploaded;
	}

	public int getSrNo() {
		return srNo;
	}

	public void setSrNo(int srNo) {
		this.srNo = srNo;
	}

	public String getDocumentName() {
		return documentName;
	}

	public void setDocumentName(String documentName) {
		this.documentName = documentName;
	}

}
2. JSF code (MultpleFileUpload.xhtml)
<?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"
	xmlns:p="http://primefaces.org/ui">
<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
	<title>JSF Primefaces Multiple File Upload with Ajax using
		advanced mode</title>
</h:head>
<h:body>
	<h3>JSF PrimeFaces Multiple File Upload Example</h3>
	<h:form id="fileUpoadForm" prependId="false"
		enctype="multipart/form-data">

		<h:outputLabel for="txtIdName" value="Enter Your Name:" />
		<p:inputText id="txtIdName" required="true"
			value="#{fileUploadBean.name}" label="Name" />

		<p:separator />


		<p:outputPanel id="testContainer">

			<p:dataTable id="docId" var="row"
				value="#{fileUploadBean.documentList}" editable="true"
				editMode="cell" widgetVar="documentTable">

				<p:column headerText="Sr. No" style="width:3%">
					<h:outputText value="#{row.srNo}" title="Sr No" />
				</p:column>



				<p:column headerText="Document Name">
					<p:cellEditor>
						<f:facet name="output">
							<h:outputText value="#{row.documentName}" />
						</f:facet>
						<f:facet name="input">
							<p:inputText value="#{row.documentName}"
								rendered="#{row.removable}" />
						</f:facet>
					</p:cellEditor>
				</p:column>

				<p:column headerText="Institute">
					<p:cellEditor>
						<f:facet name="output">
							<h:outputText value="#{row.institute}" />
						</f:facet>
						<f:facet name="input">
							<p:inputText value="#{row.institute}" />
						</f:facet>
					</p:cellEditor>
				</p:column>

				<p:column headerText="File">
					<p:panel rendered="#{!row.uploaded}">
						<p:fileUpload value="#{fileUploadBean.document}"
							fileUploadListener="#{fileUploadBean.uploadDoc_Advanced}"
							mode="advanced" dragDropSupport="false" update="@this,docId"
							allowTypes="/(\.|\/)(gif|jpe?g|png)$/">
							<f:attribute name="docObj" value="#{row}"></f:attribute>
						</p:fileUpload>
					</p:panel>
					<p:panel rendered="#{row.uploaded}">
                          Doc  Uploaded       <p:commandLink
							title="remove" value="remove document"
							actionListener="#{fileUploadBean.removeDoc(row)}" update="docId"
							ajax="true" process="@this" />

					</p:panel>
				</p:column>

				<p:column headerText="Action">
					<h:outputText value="Not Removable" rendered="#{!row.removable}" />
					<p:commandButton icon="ui-icon-close" title="remove"
						actionListener="#{fileUploadBean.removeRow(row)}" update="docId"
						ajax="true" rendered="#{row.removable}" process="@this" />

				</p:column>

			</p:dataTable>
		</p:outputPanel>

		<p:commandButton value="Upload More Document" process="@this"
			update="docId" actionListener="#{fileUploadBean.addNewDoc}"
			ajax="true" />
		<p:commandButton value="Submit" action="#{fileUploadBean.updatePage}" />


	</h:form>

</h:body>
</html>
3. Create managed bean (MultipleFileUploadBean.java)
package net.javaonline.jsf.primefaces.multiplefileupload.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.apache.commons.io.FilenameUtils;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

@ManagedBean(name = "fileUploadBean")
@ViewScoped
public class MultipleFileUploadBean implements Serializable {

	
	private static final long serialVersionUID = 1L;

	private String name;
	private UploadedFile document;
	ArrayList<DocumentModel> documentList = new ArrayList<DocumentModel>();

	public String getName() {
		return name;
	}

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

	public UploadedFile getDocument() {
		return document;
	}

	public void setDocument(UploadedFile document) {
		this.document = document;
	}

	public ArrayList<DocumentModel> getDocumentList() {
		return documentList;
	}

	public void setDocumentList(ArrayList<DocumentModel> documentList) {
		this.documentList = documentList;
	}

	public MultipleFileUploadBean() {
		try {
			documentList = initialize();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public ArrayList<DocumentModel> initialize() throws IOException {

		ArrayList<DocumentModel> list = new ArrayList<DocumentModel>();
		DocumentModel obj = new DocumentModel();
		obj.setSrNo(1);
		obj.setDocumentName("10th Marksheet");
		obj.setRemovable(false);
		list.add(obj);
		obj = new DocumentModel();
		obj.setSrNo(2);
		obj.setDocumentName("+2 Marksheet");
		obj.setRemovable(false);
		list.add(obj);
		return list;
	}

	public String addNewDoc() throws IOException {

		ArrayList<DocumentModel> list = getDocumentList();
		System.out.println("list count= " + list.size()
				+ list.get(list.size() - 1).srNo);
		DocumentModel obj = new DocumentModel();
		obj.setSrNo(list.get(list.size() - 1).srNo + 1);
		obj.setDocumentName("Type Document Name here");
		obj.setInstitute("Type Institute here");
		list.add(obj);

		setDocumentList(list);

		return null;

	}

	public String removeRow(DocumentModel row) {
		documentList.remove(row);
             //updates serial no.
              int i=0;
               for (DocumentModelSimple fl : documentList) {

               i++;
               fl.setSrNo(i);
              }
		return null;
	}

	public String removeDoc(DocumentModel row) {

		System.out.println("filename to be removed "
				+ row.getDocumentUploadedPath());
//You can write logic to remove uploaded file from the device. not written here.  

		row.setDocumentUploadedPath("");
		row.setUploaded(false);

		return null;
	}

	public String uploadDoc_Advanced(FileUploadEvent e) throws IOException {

		DocumentModel docObj = (DocumentModel) e.getComponent().getAttributes()
				.get("docObj");

		document = e.getFile();

		String fileName = "";

		String filePath = "c:/temp/kk/";
		byte[] bytes = null;

		if (null != document) {
			bytes = document.getContents();
			fileName = FilenameUtils.getName(document.getFileName());
			System.out.println("file name" + fileName);
			BufferedOutputStream stream = new BufferedOutputStream(
					new FileOutputStream(new File(filePath + fileName)));
			stream.write(bytes);
			stream.close();
		}

		docObj.setUploaded(true);
		docObj.setDocumentUploadedPath(filePath + fileName);
		documentList.set(documentList.indexOf(docObj), docObj);

		System.out.println("File Uploaded");

		return null;
	}

	public String updatePage() throws IOException {

		ArrayList<DocumentModel> list = getDocumentList();

		int i = 0;

		StringBuffer resultTemp = new StringBuffer();

		// DB (DAO) code may be called here that is to capture all document
		// details. I have not written this part of code.

		for (DocumentModel fl : list) {

			i++;

			resultTemp.append(i + ". Document Name : " + fl.documentName
					+ ", File Path: " + fl.getDocumentUploadedPath());
		}

		FacesContext.getCurrentInstance().addMessage(null,
				new FacesMessage(resultTemp.toString()));

		// setResult(resultTemp.toString());

		return "success";

	}

}
Method II) Using p:fileUpload with simple mode:

Here in simple mode, we will upload all files/ documents at one go by clicking on the form  submit button.  More documents can also be added dynamically.

1. Create Document Upload Model Simple (DocumentModelSimple.java):

 

package net.javaonline.jsf.primefaces.multiplefileupload.controller;

import java.io.Serializable;
import org.primefaces.model.UploadedFile;

public class DocumentModelSimple implements Serializable {
	int srNo;
	String documentName;
	String institute;
	boolean removable = Boolean.TRUE;
	boolean uploaded = Boolean.FALSE;
	private UploadedFile documentS;

	public void setDocumentS(UploadedFile documentS) {
		this.documentS = documentS;
	}

	public UploadedFile getDocumentS() {
		return documentS;
	}

	public boolean isRemovable() {
		return removable;
	}

	public void setRemovable(boolean removable) {
		this.removable = removable;
	}

	public String getInstitute() {
		return institute;
	}

	public void setInstitute(String institute) {
		this.institute = institute;
	}

	public boolean isUploaded() {
		return uploaded;
	}

	public void setUploaded(boolean uploaded) {
		this.uploaded = uploaded;
	}

	public int getSrNo() {
		return srNo;
	}

	public void setSrNo(int srNo) {
		this.srNo = srNo;
	}

	public String getDocumentName() {
		return documentName;
	}

	public void setDocumentName(String documentName) {
		this.documentName = documentName;
	}

}
2. JSF code (MultpleFileUpload_Simple_Mode.xhtml):
<?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"
	xmlns:p="http://primefaces.org/ui">
<h:head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
	<title>JSF Primefaces Multiple File Upload on Submit using
		Simple mode</title>
</h:head>
<h:body>
	<h3>JSF PrimeFaces Multiple file Upload Example</h3>
	<h:form id="fileUpoadForm" prependId="false"
		enctype="multipart/form-data">

		<h:outputLabel for="txtIdName" value="Enter Your Name:" />
		<p:inputText id="txtIdName" required="true"
			value="#{fileUploadBeanSimple.name}" label="Name" />

		<p:separator />


		<p:outputPanel id="testContainer">

			<p:dataTable id="docId" var="row"
				value="#{fileUploadBeanSimple.documentList}" editable="true"
				editMode="cell" widgetVar="documentTable">

				<p:column headerText="Sr No" style="width:3%">
					<h:outputText value="#{row.srNo}" title="Sr No" />
				</p:column>



				<p:column headerText="Document Name">
					<p:cellEditor>
						<f:facet name="output">
							<h:outputText value="#{row.documentName}" />
						</f:facet>
						<f:facet name="input">
							<p:inputText value="#{row.documentName}"
								rendered="#{row.removable}" />
						</f:facet>
					</p:cellEditor>
				</p:column>

				<p:column headerText="Institute">
					<p:cellEditor>
						<f:facet name="output">
							<h:outputText value="#{row.institute}" />
						</f:facet>
						<f:facet name="input">
							<p:inputText value="#{row.institute}" />
						</f:facet>
					</p:cellEditor>
				</p:column>


				<p:column headerText="File">
					<p:panel>
						<p:fileUpload value="#{row.documentS}" mode="simple"
							dragDropSupport="false" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
					</p:panel>
				</p:column>
				<p:column headerText="Action">
					<p:panel>

						<h:outputText value="Not Removable" rendered="#{!row.removable}" />
						<p:commandButton icon="ui-icon-close" title="remove"
							actionListener="#{fileUploadBeanSimple.removeRow(row)}"
							update="docId" ajax="true" rendered="#{row.removable}"
							process="@this" />
					</p:panel>
				</p:column>

			</p:dataTable>
		</p:outputPanel>

		<p:commandButton value="Upload More Document" process="@this"
			update="docId" actionListener="#{fileUploadBeanSimple.addNewDoc}"
			ajax="true" />
		<p:commandButton value="Submit"
			action="#{fileUploadBeanSimple.uploadDocuments}" ajax="false" />


	</h:form>

</h:body>
</html>
3. Create Managed Bean (MultpleFileUploadBeanSimple.java):
package net.javaonline.jsf.primefaces.multiplefileupload.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;

import org.apache.commons.io.FilenameUtils;

@ManagedBean(name = "fileUploadBeanSimple")
@ViewScoped
public class MultipleFileUploadBeanSimple implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	ArrayList<DocumentModelSimple> documentList = new ArrayList<DocumentModelSimple>();

	public String getName() {
		return name;
	}

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

	public ArrayList<DocumentModelSimple> getDocumentList() {
		return documentList;
	}

	public void setDocumentList(ArrayList<DocumentModelSimple> documentList) {
		this.documentList = documentList;
	}

	public MultipleFileUploadBeanSimple() {
		try {
			documentList = initialize();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public ArrayList<DocumentModelSimple> initialize() throws IOException {

		ArrayList<DocumentModelSimple> list = new ArrayList<DocumentModelSimple>();
		DocumentModelSimple obj = new DocumentModelSimple();
		obj.setSrNo(1);
		obj.setDocumentName("10th Marksheet");
		obj.setRemovable(false);
		list.add(obj);
		obj = new DocumentModelSimple();
		obj.setSrNo(2);
		obj.setDocumentName("+2 Marksheet");
		obj.setRemovable(false);
		list.add(obj);
		return list;
	}

	public String addNewDoc() throws IOException {

		ArrayList<DocumentModelSimple> list = getDocumentList();
		System.out.println("list count= " + list.size()
				+ list.get(list.size() - 1).srNo);
		DocumentModelSimple obj = new DocumentModelSimple();
		obj.setSrNo(list.get(list.size() - 1).srNo + 1);
		obj.setDocumentName("Type Document Name here");
		obj.setInstitute("Type Institute here");
		list.add(obj);

		setDocumentList(list);

		return null;

	}

	public String removeRow(DocumentModelSimple row) {
		documentList.remove(row);
             //updates serial no.
            int i=0;
               for (DocumentModelSimple fl : documentList) {
                   i++;
                   fl.setSrNo(i);
                } 
		return null;
	}

	public String removeDoc(DocumentModelSimple row) {
		row.setUploaded(false);
		return null;
	}

	public String uploadDocuments() throws IOException {

		ArrayList<DocumentModelSimple> list = getDocumentList();

		int i = 0;

		StringBuffer resultTemp = new StringBuffer();

		String filePath = "c:/temp/kk/";
		String filename = "";
		for (DocumentModelSimple fl : list) {
			byte[] bytes = null;

			if (null != fl.getDocumentS()) {
				bytes = fl.getDocumentS().getContents();
				filename = FilenameUtils.getName(fl.getDocumentS()
						.getFileName());
				BufferedOutputStream stream = new BufferedOutputStream(
						new FileOutputStream(new File(filePath + filename)));
				stream.write(bytes);
				stream.close();
			}

			i++;

			resultTemp.append(i + ". Document Name : " + fl.documentName
					+ ", File Path: " + filename);
		}

		FacesContext.getCurrentInstance().addMessage(null,
				new FacesMessage(resultTemp.toString()));

		return "success";

	}

}
Result Page (success.xhtml):
<?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"
	xmlns:p="http://primefaces.org/ui">

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


	<h2>Below Documents uploaded  </h2>
		<p> <h:messages id="messages" /></p>

</h:body>
</html>
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 Primefaces Multiple File Upload Example</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>
  
  
    <context-param>
            <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
            <param-value>true</param-value>
      </context-param>
  

  <context-param>
    <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
  </context-param>
  <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>resources.application</param-value>
  </context-param>
 <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>
  

      
  
  <listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
  </listener>
</web-app>

Run the application by calling the below urls

For uploading of each file individually:

1. http://localhost:8080/JSFPrimeFacesMultipleFileUpload/faces/MultipleFileUpload.xhtml

multiple file upload advanced

Select file and click on upload for each file.

multiple file upload advanced1

The  qualifications other than not removable can  be removed by clicking on the  close button.

multiple file upload advanced2

Uploaded files can be removed by clicking on the remove document link.

Click on submit button to update the document details and to display result page.

multiple file upload advanced result

 

 

For uploading of all files at one go by form submit button:

2. http://localhost:8080/JSFPrimeFacesMultipleFileUpload/faces/MultipleFileUpload_Simple_Mode.xhtml

multiple file upload simple

Select necessary  files and add more documents dynamically if necessary. Click on submit button to upload all selected documents at one go.

multiple file upload simple1

Result Page

multiple file upload simple result

Note: Don’t Forget to enter name. You may get the below error if you forget to enter in the name field.

java.io.NotSerializableException: org.apache.catalina.core.StandardPart

java.io.NotSerializableException: org.apache.catalina.core.StandardPart
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
....
....

 

Reference:  Primeface multiple file upload

 

Leave a Reply