Because I am constantly busy working on something, I have never had time to actually put everything in words and pictures. But, since you got here, then you must have already seen some part of my work - and this is the way I’m talking. I'm 24, born in Romania, studied at UPG Romania in software development field. I started from 0, mostly with basic stuff, and I’m evolving every day to an expert. I'm focused on freelancing projects, from small websites, to really heavy stuff.

Saturday, April 3, 2010

PPR multi-file upload with PrimeFaces 2.0


The below recipe is just an example of what you can find in the JSF 2.0 Cookbook from Packt.


In this recipe you will see how to use a great PrimeFaces 2.0 component for multi-file upload with PPR support. Notice that PrimeFaces offers four types of upload as follows:
• Single Upload
• Multiple File Upload
• Auto Upload
• PPR Integration (presented in this recipe)

PPR stands for Partial Page Rendering, which means that after a file is uploaded you can update any JSF component. Our example will update a growl notifier, which is another PrimeFaces great component.
Getting ready
We developed this recipe with NetBeans 6.8, JSF 2.0 and GlassFish v3. The JSF 2.0 classes were obtained from NeBeans JSF 2.0 bundled library. In addition, we have used PrimeFaces 2.0, which provide support for JSF 2.0. You can download this distribution from http://www.primefaces.org/.
How to do it...
Practically, PrimeFaces offers these four uploads types through a single component named p:fileUpload, and configured through its attributes as follows:

• for single upload the multiple attribute is set to false;
• for multiple upload the multiple attribute is set to true;
• for auto upload the auto attribute is set to true;
• for PPR integration effect, the update attribute should indicate the id of the JSF component to be updated after a file was uploaded successfully or not.

Now, we wrote a JSF form that integrates the fileUpload component with the following characteristics:

• multiple file-upload – multiple attribute set to true;
• limit upload size – sizeLimit attribute set to the desired limit in bytes;
• upload only pictures – extensions listed in allowTypes attribute;
• update a growl component – id was specified in update attribute;

Now, the p:fileUpload complete tag reference is available at http://primefaces.prime.com.tr/docs/tag/. You will be pleased to find out that you can customize this component exactly as you want.
Now, let’s see code of JSF page for our upload:

<h:form enctype="multipart/form-data" prependId="false">
<p:growl id="messages" showSummary="true" showDetail="true" />
<p:fileUpload fileUploadListener="#{uploadBean.handleFileUpload}"
update="messages" sizeLimit="1073741824"
multiple="true" label="choose" allowTypes="*.jpg;*.png;*.gif;"
description="Images"/>
</h:form>
The PrimeFaces p:growl component “brings the Mac's growl widget to JSF with the ability of displaying FacesMessages. Growl simply replaces h:messages component.”

Now, the UploadBean implements the hadleFileUpload method like this:
public class UploadBean {

private static final int BUFFER_SIZE = 6124;

/** Creates a new instance of UploadBean */
public UploadBean() {
}

public void handleFileUpload(FileUploadEvent event) {

ExternalContext extContext = FacesContext.getCurrentInstance().
getExternalContext();
File result = new File(extContext.getRealPath
("//WEB-INF//upload") + "//" + event.getFile().getFileName());

try {
FileOutputStream fileOutputStream = new FileOutputStream(result);

byte[] buffer = new byte[BUFFER_SIZE];

int bulk;
InputStream inputStream = event.getFile().getInputstream();
while (true) {
bulk = inputStream.read(buffer);
if (bulk < 0) {
break;
}
fileOutputStream.write(buffer, 0, bulk);
fileOutputStream.flush();
}

fileOutputStream.close();
inputStream.close();

FacesMessage msg = new FacesMessage("Succesful",
event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);

} catch (IOException e) {
e.printStackTrace();

FacesMessage error = new FacesMessage("The files were
not uploaded!");
FacesContext.getCurrentInstance().addMessage(null, error);
}
}
}
The upload example is ready, but we still need to add some configuration in web.xml descriptor (these configurations are not altering the PrimeFaces default configurations). These are specific to upload process and they are listed next:

• set the javax.faces.STATE_SAVING_METHOD context param to server:
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
• optionally, you may specify a temporary folder for storing the uploaded files, like this:
<init-param>
<param-name>uploadDirectory</param-name>
<param-value>/tmp/fileUpload</param-value>
</init-param>
• add the PrimeFaces FileUpload Filter as a filter for the Faces Servlet (keep in mind that this should be the first filter in web.xml, if you have more):
<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>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Now, if test our upload you will see something like in figure below:

How it works...
As you can see the PrimeFaces upload is based on a filter and on a listener. The filter intercepts requests in front of Faces Servlet and detects the upload requests, while the listener has the particularity that requires an FileUploadEvent object, which extends the javax.faces.event.FacesEvent. The upload process is configured in the JSF page through p:uploadFile component, and it is controlled by the developer in the listener implemented in managed bean, like you just saw.

The above recipe is just an example of what you can find in the JSF 2.0 Cookbook from Packt.

9 comments:

Anonymous said...

Thank you very much for this very instructive tuto!
I begin with primefaces and i had some trouble to get fileupload component working. Now it works perfectly!

Anonymous said...

thanks for sharing this. it really helps.

ziedff said...

it's not work :(
the p:grow it's not updated !!!

Big Rob Cooper said...

Thank you very much. Any pointers on how to show the pictures now.

Egidio De Lorenzo said...

Thank you very much!

Anonymous said...

thank you ,

...now i start searching for how to upload to FTP :D

jundi said...

really good,

how can i use another commandbutton to save some data and trigger the upload event.

rachel said...

nice article

John Ortiz said...

I have established multiple="false" property, but it lets to attach more files.

What is happening?

Thanks.