ShowTable of Contents
Introduction
This article explains how to implement multiple file uploads, along with HTML form elements in a portlet application, by leveraging the features of JavaTM Portlet Specification V2.0 (JSR 286) portlets to download the file. The file upload can be stored on disk or in database, and we discuss how to store the file on the disk and later retrieve it, using the serverresourceurl method.
Use case
Consider a simple scenario in which you enter your name, age, and gender in an HTML form, then upload two documents, and click Submit (see figure 1). On submit, the documents are stored on disk, and URLs are provided for downloading the files in the next window (see figure 2).
Figure 1. Window in which to enter form details and upload files
Figure 2. Window displayed after clicking Submit
When you click the URL link, a pop-up window displays for downloading the file (see figure 3).
Figure 3. File Download window
Portlet development
Implementing file upload
We have implemented the above use case by using a basic JSR 286 portlet. For implementing the multiple-file-upload option we need to import a commonsfileupload.jar from the
Apache Commons Web site. As described on that site:
FileUpload parses the request and provides the application with a list of the individual uploaded items, each of which implements the FileItem interface, regardless of its underlying implementation.
The item can be a regular form field---that is, the data came from an ordinary text box or similar HTML field---or an uploaded file, and the FileItem interface provides the methods to make such a determination and to access the data in the most appropriate manner.
FileUpload creates new file items using a FileItemFactory. This is what gives FileUpload most of its flexibility. The factory has ultimate control over how each item is created. The factory implementation that currently ships with FileUpload stores the item's data in memory or on disk, depending on the size of the item (i.e., bytes of data).
Starting with version 1.1, FileUpload supports file upload requests in both servlet and portlet environments.
Listing 1 shows the code snippet of the processAction method whereby the request is parsed depending on whether the item is a form field or a file upload.
Listing 1. Code to parse request
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException {
// Check that we have a file upload request
boolean isMultipart = PortletFileUpload.isMultipartContent(request);
try {
if (isMultipart) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
PortletFileUpload upload = new PortletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
response.setRenderParameter(name, value);
} else {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
String filesize = "" + sizeInBytes;
File uploadedFile = new File("C:\\UploadTrials\\" + fieldName + ".doc");
int filelength = (int)uploadedFile.length();
item.write(uploadedFile);
response.setRenderParameter(fieldName, "C:\\UploadTrials\\" + fieldName + ".doc")
}
}
}
} catch ( Exception e) {
System.out.println("SampleFileUploadPortlet.processAction() Error occured");
e.printStackTrace();
}
}
The code snippet below checks whether the file Element is present in the request; if yes, then the Multipart would be set to true:
// Check that we have a file upload request
boolean isMultipart = PortletFileUpload.isMultipartContent(request);
First we parse the request to ensure it is a FileUpload request:
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
PortletFileUpload upload = new PortletFileUpload(factory);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
The result of the parse is a list of FileItems, each of which implements the FileItem Interface. This list can now be iterated and, depending on whether it is a form field or file upload, the respective business logic can be implemented. In this use case, it stores the file upload to a disk.
Implementing file download
To implement the file download option we leverage the serverresourceurl method of JSR 286 portlet. Listing 2 is a code snippet in the Java ServerPages (JSP) to invoke the serveResource method.
Listing 2. Code to invoke serveResource method
}
<TR>
<TD>Document 1</TD>
<TD><a href="<portlet:resourceURL> <portlet:param name="uploadfile1" value="<%=uploadfile1%>" />
</portlet:resourceURL>"> <%=uploadfile1 %></a></TD>
</TR>
We create portlet resourceURL event to invoke the serveResource method and also pass the filename as a parameter to the same.
Listing 3 is the code snippet for the serveResource method.
Listing 3. Code for serveResource method
public void serveResource(ResourceRequest req, ResourceResponse res)
throws PortletException, IOException {
String uploadfile1 = req.getParameter("uploadfile1");
res.setContentType("application/x-ms-word");
File file = new File(uploadfile1);
OutputStream outStream = res.getPortletOutputStream();
if (!file.exists() || !file.canRead()) {
outStream.write("<i>Unable to find the specified file</i>"
.getBytes());
} else {
FileInputStream inStream = new FileInputStream(file);
res.setProperty("Content-disposition", "attachment; filename=\"" + uploadfile1 + "\"");
byte[] buffer = new byte[1024];
while (true) {
int bytes = inStream.read(buffer);
if (bytes <= 0) {
break;
}
outStream.write(buffer, 0, bytes);
}
}
outStream.flush();
outStream.close();
}
Finally, we retrieve the parameter passed to the resourceURL event and, using fileInputStream, we write the contents of the file.
Deploying
Attached to this article is a sample FileUpload .war file containing the sample code. Follow these steps to run the sample code:
- Create a folder called UploadTrials on your C drive.
- Detach the .war file provided in the attachment.
- Create a sample portal page.
- Attach the portlet on the page.
- Test the portlet by uploading a Microsoft Word document file.
Resources
About the author
Asif Palimar is an IT Specialist with IBM India Software Labs. He has extensive experience in working on multiple portal products. He currently works for the Lab Services division within the Software Lab, where he specializes in WebSphere Portal and participates in various customer-facing engagements. He can be reached at
aspalima@in.ibm.com.