Without knowing if it is the best approach or not, I will post how I solved the multiple file upload problem in JSF as follows.
Here is the xhtml file that would take the files
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:t="http://myfaces.apache.org/tomahawk">
<h:head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js">
</script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<h:outputScript library="javascript" name="amharic.js"/>
<title>OH YEA, PUT your face HERE</title>
</h:head>
<h:body>
<h:form id="uploadForm" enctype="multipart/form-data">
<h:panelGrid columns="3">
<h:outputLabel for="file1" value="Select file" />
<t:inputFileUpload id="file1" value="#{myBean.uploadedFile}" required="true" />
<h:message for="file1" style="color: red;" />
<h:outputLabel for="file2" value="Select file" />
<t:inputFileUpload id="file2" value="#{myBean.uploadedFile}" required="false" />
<h:message for="file2" style="color: red;" />
<h:outputLabel for="file3" value="Select file" />
<t:inputFileUpload id="file3" value="#{myBean.uploadedFile}" required="false" />
<h:message for="file3" style="color: red;" />
<h:panelGroup />
<h:commandButton value="save" action="#{myBean.uploadFiles}" />
<h:message for="uploadForm" infoStyle="color: green;" errorStyle="color: red;" />
</h:panelGrid>
</h:form>
</h:body>
</html>
As you can see, the file would be dealing with a single backing bean property uploadedFile. You would tomahawk for the file upload one. There is also file upload in richfaces as well.
Now, let’s see what is the hood of MyBean.java. In the bean you would have to member variables for this purpose:
private List<UploadedFile> uploadedFiles;
private UploadedFile uploadedFile;
You can get the uploaded file from org.apache.myfaces.custom.fileupload.UploadedFile.
Then have a normal getter and setter for both.
The trick is in the setter of the uploadedFile:
public void setUploadedFile(UploadedFile uploadedFile){
this.uploadedFiles.add(uploadedFile);
}
When the file is requested, add it to the list of the uploadedFiles.
For the action which would would do the actual uploading of the file, I have used the snippet from http://balusc.blogspot.com/2008/02/uploading-files-with-jsf.html.
public String uploadFiles(){
for(UploadedFile uploadedFile : this.uploadedFiles){
if (uploadedFile !=null ){
// Prepare filename prefix and suffix for an unique filename in upload folder.
String prefix = FilenameUtils.getBaseName(uploadedFile.getName());
String suffix = FilenameUtils.getExtension(uploadedFile.getName());
// Prepare file and outputstream.
File file = null;
OutputStream output = null;
try {
// Create file with unique name in upload folder and write to it.
file = File.createTempFile(prefix + "_", "." + suffix, new File("Your_Path"));
output = new FileOutputStream(file);
IOUtils.copy(uploadedFile.getInputStream(), output);
// Show succes message.
FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage(
FacesMessage.SEVERITY_INFO, "File upload succeed!", null));
} catch (IOException e) {
// Cleanup.
if (file != null) file.delete();
// Show error message.
FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage(
FacesMessage.SEVERITY_ERROR, "File upload failed with I/O error.", null));
// Always log stacktraces (with a real logger).
e.printStackTrace();
} finally {
IOUtils.closeQuietly(output);
}
}
}
return "done";
}