Sep 1, 2012

Form-based File Upload in J2EE Web Application Part 1

Many times we may have a file upload control on view asking user to upload a file or an image from local machine. HTML provides  a file control to upload a file. But on server side, we need to write a code to save it on a file server.

In J2EE, file upload functionality can be best achieved using Commons File Upload. A file upload request comprises an ordered list of items that are encoded according to RFC-1867. FileUpload can parse such a request and provide your application with a list of the individual uploaded items. Each such item implements the FileItem interface, regardless of its underlying implementation.

Each file item has a number of properties that might be of interest for your application. For example, every item has a name and a content type, and can provide an InputStream to access its data. On the other hand, you may need to process items differently, depending upon whether the item is a regular form field - that is, the data came from an ordinary text box or similar HTML field - or an uploaded file. The FileItem interface provides the methods to make such a determination, and to access the data in the most appropriate manner.

Before you can work with the uploaded items, of course, you need to parse the request itself. Ensuring that the request is actually a file upload request is straightforward, but FileUpload makes it simplicity itself, by providing a static method to do just that.

Let's make a very simple application to upload a file using JSP/Servlets as shown in following image.

Prerequisites


For this tutorial, we will need the following tools: (The older or newer version should also works). Moreover, basic Java knowledge is assumed.

  1. Eclipse IDE for Java EE Developers
  2. Apache Tomcat v6 or later
  3. Apache Commons IO 
  4. Apache Commons File Upload
Apache commons IO and File Upload jars has to be put in your web application lib folder. Following is the folder structure for this example.


Create a View using JSP


The view includes a simple file upload control with submit button. Following is the code:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<form action="upload.do" method="post" enctype="multipart/form-data">
 Select file to upload: <input type="file" name="selectFile" /> <br />
 <input type="submit"> 
</form>


</body>
</html> 

 

Creating a Controller 

Controller will receive the multipart request. It will save the file at folder location configured in context parameters of the web application. It also creates a map of regular form parameters if any. We dont have any regular form parameter in this example. But that's put for your reference only.

package org.avid.upload.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * @author Jay Rajani
 * 
 * Servlet implementation class UploadController
 */
public class UploadController extends HttpServlet {
 private static final long serialVersionUID = 1L;
 
 private String folderLocation = null; 
 
 @Override
 public void init() throws ServletException {
  super.init();
  this.folderLocation = getServletContext().getInitParameter("UPLOAD_FOLDER");
 }

 /**
  * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  
  HashMap<String, String> formParams = new HashMap<String, String>();
  
  // Check that we have a file upload request
  boolean isMultipart = ServletFileUpload.isMultipartContent(request);
  
  try{
   if (isMultipart){
    
    // Create a factory for disk-based file items
    FileItemFactory factory = new DiskFileItemFactory();

    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(factory);

    // Parse the request
    List<FileItem> items = upload.parseRequest(request);
    
    // Process the uploaded items
    Iterator<FileItem> iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();

        if (item.isFormField()) {
         
         // Process a regular form field
         formParams.put(item.getFieldName(), item.getString());
        } else {
         
         // Process a file upload
         String fileName = item.getName();
         
         File uploadedFile = new File(folderLocation+File.separator+fileName);
            item.write(uploadedFile);
        }
    }
   }
  }catch(FileUploadException fue){
   fue.printStackTrace();
   throw new ServletException(fue.getMessage());
  }catch(Exception e){
   e.printStackTrace();
   throw new ServletException(e.getMessage());
  }
 }

}


Deployment Descriptor


Here is the snippet of final deployment descriptor.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 
 <context-param>
  <param-name>UPLOAD_FOLDER</param-name>
  <param-value>E:/temp</param-value>
 </context-param>
 
 <display-name>FileUpload</display-name>
 
 <servlet>
  <description>
  </description>
  <display-name>UploadController</display-name>
  <servlet-name>UploadController</servlet-name>
  <servlet-class>
  org.avid.upload.controller.UploadController</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>UploadController</servlet-name>
  <url-pattern>/upload.do</url-pattern>
 </servlet-mapping>

</web-app>

The code will save the file to location specified in web.xml. It can be a local folder or shared folder or ftp location depending on your requirement.