File upload with Apache MyFaces Tomahawk

In this recipe, you will see how to implement a JSF application for uploading files using a dedicated component developed under the Apache MyFaces Tomahawk project.

Getting ready

We developed this recipe with NetBeans 6.8, JSF 1.2, and GlassFish v3. The JSF 1.2 classes were obtained from the NetBeans JSF 1.2 bundled library. In addition, we have used Apache MyFaces Tomahawk 1.1.9, which provides support for JSF 1.2. You can download this distribution from http://myfaces.apache.org/tomahawk/index.html. The Apache MyFaces Tomahawk libraries (including necessary dependencies) are in the book code bundle, under the /JSF_libs/Apache Tomahawk JSF 1.2 folder.

How to do it...

As we said earlier, this time we will implement an upload application using Apache MyFaces Tomahawk. To be more exactly, we will use a dedicated tag, named inputFileUpload. The tag class of this component is HtmlInputFileUploadTag and it creates a file-selection widget in the rendered page, which allows a user to select a file for uploading to the server. The following table—extracted from the official javadoc—describes the most used attributes of this tag:

Name

Required

Description

storage

No

This setting was intended to allow control over how the contents of the file get temporarily stored during processing.

It allows three options:

"default": The file is handled in memory while the file size is below uploadThresholdSize value, otherwise it is handled on disk or file storage when decode occur (set submitted value).

"memory": The file is loaded to memory when decode occur (set submitted value). In other words, before setting the uploaded file a submitted value it is loaded to memory. Use with caution, because it could cause OutOfMemory exceptions when the uploaded files are too big. "file": The file is handled on disk or file storage.

value

No

An EL expression to which an UploadedFile object will be assigned on postback if the user specified a file to upload to the server.

required

No

A Boolean value that indicates whether an input value is required.

binding

No

Identifies a backing bean property (of type UIComponent or appropriate subclass) to bind to this component instance. This value must be an EL expression.

Now, based on the description of the attributes, we have configured the following inputFileUpload tag:

<h:panelGrid columns="3">
<h:outputLabel for="fileID" value="Choose a file to upload:" />
<t:inputFileUpload id="fileID"
value="#{uploadBean.uploadedFile}"
storage="file"
required="true" />
<h:message showSummary="true" showDetail="false" for="fileID"
style="color: red; text-decoration:overline"/>
<h:panelGroup />
<h:commandButton value="Submit" action="#{uploadBean.submit}" />
<h:message for="uploadForm" infoStyle="color: blue;"
errorStyle="color: red;" />
</h:panelGrid>

Now, let's focus on the value attribute. This attribute indicates a bean that is responsible for the upload process (take a closer look on the UploadedFile object, since this is the "brain" of our bean—it is pretty intuitive what is going on). We have implemented this bean as shown next:

package uploadpkg;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
public class UploadBean {
private UploadedFile uploadedFile;
private String fileName;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public String getFileName() {
return fileName;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void submit() {
// Get information you from the uploaded file
System.out.println("Uploaded file name: "
+ uploadedFile.getName());
System.out.println("Uploaded file type: "
+ uploadedFile.getContentType());
System.out.println("Uploaded file size: "
+ uploadedFile.getSize() + " bytes");
try {
//Upload success
FacesContext.getCurrentInstance().addMessage
("uploadForm", new FacesMessage
(FacesMessage.SEVERITY_INFO,
"File upload was a total success!", null));
} catch (Exception e) {
//Upload failed
FacesContext.getCurrentInstance().addMessage
("uploadForm", new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"File upload was a failed.", null));
e.printStackTrace();
}
}
}

Note that this bean doesn't actually write the uploaded file on server. When the submit method is called, it contains information about the uploaded file (name, type, size, and so on) and access to its InputStream through the uploadedFile.getInputStream() method (another example of exploiting this method can be seen in the recipe Extracting data from an uploaded CVS file). Having the InputStream and the uploaded filename, you can develop a method as shown next:

public static void write(File file, InputStream input,
boolean append) throws IOException {
mkdirs(file);
BufferedOutputStream output = null;
try {
output = new BufferedOutputStream(
new FileOutputStream(file, append));
int data = -1;
while ((data = input.read()) != -1) {
output.write(data);
}
} finally {
close(input, file);
close(output, file);
}
}

The append argument of the write method indicates if the uploaded content will be appended to the file file or if it should overwrite the existing one (if there is one).

How it works...

There are no secrets behind the scenes. It looks like a classic upload component that creates a file-selection widget in the rendered page, which allows a user to select a file for uploading to the server. The upload process is controlled from a bean through an instance of the org.apache.myfaces.custom.fileupload.UploadedFile class. This object provides us enough information for controlling the uploaded file.

There's more...

It is not required, but you can configure the Tomahawk ExtensionsFilter with one or more of the following useful init-param settings, which you can put in the <filter> tag (this should appear in the web.xml file):

<init-param>
<description>
Set the size limit for uploaded files.
Format: 10 - 10 bytes
10k - 10 KB
10m - 10 MB
1g - 1 GB
</description>
<param-name>uploadMaxFileSize</param-name>
<param-value>100m</param-value>
</init-param>
<init-param>
<description>
Set the threshold size - files below this limit are stored
in memory, files above this limit are stored on disk.
Format: 10 - 10 bytes
10k - 10 KB
10m - 10 MB
1g - 1 GB
</description>
<param-name>uploadThresholdSize</param-name>
<param-value>100k</param-value>
</init-param>
<init-param>
<description>
Set the path where the intermediary files will be stored.
</description>
<param-name>uploadRepositoryPath</param-name>
<param-value>/temp</param-value>
</init-param>

See also

The code bundled with this book contains a complete example of this recipe. The project can be opened with NetBeans 6.8 and it is named: Files_upload_with_Apache_MyFaces_Tomahawk.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset