Primefaces File Upload made simple

The PrimeFaces File upload component can perform server side file uploads using a straightforward client API. In this tutorial we will therefore show a step-by-step guide on how to upload files with Primefaces version 14.0.0 (May 2024) .

Setting up the Web project

Firstly, create a Web project using Maven with the following dependencies in it:

<dependencies>
    <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-api</artifactId>
        <version>${jakartaee.version}</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.primefaces</groupId>
        <artifactId>primefaces</artifactId>
        <version>${primefaces.version}</version>
    </dependency>
</dependencies>

Please note that, if you are developing a Jakarta EE 10 application (using jakarta namespace) then you need to specify the following classifier in your dependency:

<classifier>jakarta</classifier>

Provided that you have a JSF 2.2 (or higher environment) that’s all you need. Below we will provide some details for JSF 2.1 (or older environment) which require to integrate Apache Commons library.

Next, within the web.xml file, we specify that Primefaces relies on the Native (Servlet 3.0) File uploader:

<context-param>
    <param-name>primefaces.UPLOADER</param-name>
    <param-value>native</param-value>
</context-param>

Then, add a simple index.xhtml page which contains the Form components to upload Files:

<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
 <h:body>
 
 <h:form>
    <p:fileUpload listener="#{fileUploadController.upload}" mode="advanced" dragDropSupport="false"  sizeLimit="100000"
           update="messages" sizeLimit="1000000" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" />
 
    <p:growl id="messages" showDetail="true" />
    <h3>Maximum size: 1 MB</h3>
</h:form>

      
  </h:body>
</html>

Some things worth mentioning:

  • We are using the “advanced” mode to upload files. This allows us to capture (with a listener method) the File InputStream and save it on our disk.
  • We are setting the maximum number of files to be uploaded and the regular expression to match only some file types.
  • The file size limit is 100000 bytes

Finally, on the server side, we will add the following Managed Bean to capture the file uploaded and save it:

package com.sample.bean;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.file.UploadedFile;

@ManagedBean(name = "fileUploadController")
public class FileUploadController {
    private String destination = "/tmp/";

    public void upload(FileUploadEvent event) {
        FacesMessage msg = new FacesMessage("Success! ", event.getFile().getFileName() + " is uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
        
        UploadedFile file = event.getFile();
        // Do what you want with the file
        try {
            copyFile(event.getFile().getFileName(), file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void copyFile(String fileName, InputStream in) {
        try {

            // write the inputStream to a FileOutputStream
            OutputStream out = new FileOutputStream(new File(destination + fileName));

            int read = 0;
            byte[] bytes = new byte[1024];

            while ((read = in.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }

            in.close();
            out.flush();
            out.close();

            System.out.println("New file uploaded: " + (destination + fileName));
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

Make sure you update the imports from javax to jakarta if you are deploying your application on a Jakarta EE9/10 Application Server.

A note of caution: Since the files are sent asynchronously in a separate thread on the application server, the backing bean has to be @RequestScoped!

Running the application

The example application includes WildFly plugin therefore you can run it with:

$ mvn install wildfly:deploy

Here is your application in action, after we have chosen one file for upload:

primefaces file upload tutorial

First click on “Choose” and select your file. Next, click “Upload” to upload the file.

Check on the the UI and on the Console for a log message:

New file uploaded: /tmp/picture.png

File upload with Drag and Drop

The File Uploader Client API also supports Drag and Drop of files. Just set the property “dragDropSupport” to “true”. Here is an example:

<p:fileUpload listener="#{fileUploadController.upload}" mode="advanced" dragDropSupport="true"
          update="messages" sizeLimit="1000000" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" sizeLimit="100000"/>

Using Commons libraries to upload files

As said, if your application server has no support for JSF 2.2 you have to include also Apache commons-file-upload and commons-io libraries:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

Next, as far as web.xml configuration is concerned you need to declare the PrimeFaces filter in order to enable file uploading for Apache commons:

<filter>
  <filter-name>PrimeFaces FileUpload Filter</filter-name>
  <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>PrimeFaces FileUpload Filter</filter-name>
  <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

Finally, when using PrimeFaces upload filter, you can choose the Upload Pathon the server by setting some additional parameters like uploadDirectory and thresholdSize

thresholdSize specifies the maximum file size in bytes to keep uploaded files in memory. If it
exceeds this limit, it’ll be temporarily written to disk.
uploadDirectory is the folder where to keep temporary files that exceed thresholdSize.

<filter>
  <filter-name>PrimeFaces FileUpload Filter</filter-name>
  <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
  <init-param>
    <param-name>thresholdSize</param-name>
    <param-value>51200</param-value>
  </init-param>
  <init-param>
    <param-name>uploadDirectory</param-name>
    <param-value>/tmp</param-value>
  </init-param>
</filter>

You should however not rely on these attributes to define a stable storage of uploaded file. Always use IO Streams to collect the file and then store them in your favourite storage location.

Conclusion

We have covered how to upload files in a JSF + Primefaces environment using both Servlet 3.0 API native API and Apache commons libraries

Download the example from this tutorial.