skip to main | skip to sidebar

Sunday, August 15, 2010

File Uploading Using Servlets, JSP and Commons File Upload API

I’ve seen many developers who are at the early stages of their career have problems with this topic and seen many posts in forums asking how to do it – File Uploading using Servlets, JSP!; this article will provide an example using Commons File Upload API. I tried to make the example as simple as possible, hope it helps those early birds. Example uses JSP to provide the pages with form where user can select the file to upload with other form fields, Commons File Upload API to process submitted form and read form fields separately, and Servlets as middle layer between JSP and Commons File Upload API, example also has ANT build script to generate the distributables. All the code can be downloaded, links to these resources are provided at the end of this post, lets get on with the example then.
The flow in this example is as depicted in the following picture.
Files list
As you can see, user selects the file to upload and provides normal form data as well, using "index.jsp" and submits the form to "FileUploadServlet" servlet. This servlet passes the request object to one of FormUtils class methods, and this method parses the request and creates "TestForm" class object out of the request object. This "TestForm" class object will be passed to "form-data.jsp" which in turn displays the provided data.
First we’ll go through the JSP files, we’ve two JSP files - "index.jsp", and "form-data.jsp" in this example, one to show the form with fields which user will submit, and another to show the submitted form data. Lets see what "index.jsp" has.
<html xmlns="" xml:lang="en" lang="en">
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Commons File Upload Example</title>
    <style type="text/css">
        body { font: 13px arial,helvetica,clean,sans-serif; text-align: center; }
        .container { text-align: left; width: 25em; border: 1px solid #000; padding: 0.5em; }
        .form-field { margin-bottom: 0.5em; }
        .form-field input { border: 1px solid #aaa; padding: 0.2em; }
        .btn-container { text-align: right; }
    <div class="container">
    <form action="uploadServlet" method="post" enctype="multipart/form-data">
        <div class="form-field">
            <label>Your Name: </label>
            <input type="text" name="name" size="20" />
        <div class="form-field">
            <label>Your File: </label>
            <input type="file" name="document" size="25" />
        <div class="btn-container">
            <input type="submit" value="Submit"/>
Above code has nothing special in it, just plain HTML, you might want to note two parts which are important here, one the "form" tag which has an extra attribute "enctype" and the other "input" tag with 'type' attribute as 'file'. When you want to submit a file to the server you need to have the 'enctype' attribute set to 'multipart/form-data'. And to have a form field where user can select a file and upload, you need to use the input tag with its type as 'file'. If you observe this page has one 'form' tag with 'action' attribute set to 'uploadServlet', which indicates that when user submits this form by clicking on the submit button, it'll submit the form data to a Servlet with its mapping URL ‘uploadServlet’. This form tag has two form fields – one text field with 'name' attribute as 'name' and the other a 'file' input tag with name attribute as 'document'. Now lets see the second JSP - 'form-data.jsp'.
<%@page import="com.rakesh.fileupload.form.TestForm"%>
<html xmlns="" xml:lang="en" lang="en">
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Commons File Upload Example</title>
    String error = (String)request.getAttribute("ERROR");
    if (error != null) {
        <h3><%= error %></h3>
    } else {
        TestForm form = (TestForm)request.getAttribute("DATA");
    <h2>Data Submitted is:</h2>
        Your Name: <%=form.getName()%><br/>
        File Name: <%= form.getDocument().getName() %><br/>
        File Size: <%= form.getDocument().getSize() %><br/>
        File Type: <%= form.getDocument().getContentType() %><br/>
    <% } %>
Even this JSP looks very simple except, its not simple HTML code. This page is supposed to show the data submitted by the user through 'index.jsp'. After the 'body' tag we'll first check for the request attribute 'ERROR' – when user submits the form, we'll check the submitted data and if we find any problem with the submitted data, we'll set this 'ERROR' request attribute and forward to this page. If this request attribute is set that means we have some problem with the submitted data, this error message has to be displayed to the user. We'll compare this request attribute with ‘null’ if its not null, we’ll display the error message. If this request attribute is ‘null’ – which means there is no problem with the submitted data, and we need to display the submitted information to the user, the ‘else’ block in the above code will do this for us. First line in the else block will look for a request attribute “DATA”, when the form is submitted we’ll parse the submitted request data and create one object out the those values – which is represented in our example with ‘TestForm’ class, its a POJO [Plain Old Java Object], with the corresponding fields we have in ‘index.jsp’. As mentioned earlier, ‘index.jsp’ has two form fields - ‘name’ and ‘document’, ‘TestForm’ class will have two fields in it one to hold the ‘name’ text field value and the other to hold the ‘document’ field value. Lets see the ‘TestForm’ class.
package com.rakesh.fileupload.form; 
import org.apache.commons.fileupload.FileItem;
public class TestForm {     private String name;     private FileItem document;
    public String getName() {         return name;     }
    public void setName(String name) { = name;     }
    public FileItem getDocument() {         return document;     }
    public void setDocument(FileItem document) {         this.document = document;     } }
Nothing special even here, plain Java class with two fields and setter/getter method for each of them. As the ‘name’ form field in the ‘index.jsp’ represents plain string value, the ‘name’ field in ‘TestForm’ is declared as ‘String’, and ‘document’ form field represents a file, we used “FileItem” class of Commons File Upload API. This class will provide all the information about the file which is uploaded and the provides access to the input stream for the file data. Now lets see the code which actually parses the submitted request and creates object of TestForm class.
package com.rakesh.fileupload.form; 
import java.lang.reflect.InvocationTargetException; import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class FormUtils {
    private static void processFormField(TestForm form, FileItem item)             throws IllegalArgumentException, IllegalAccessException {         try {             BeanUtils.setProperty(form, item.getFieldName(), item.getString());         } catch (InvocationTargetException e) {             // error while populating bean             return;         }     }
    private static TestForm processFileItems(List<FileItem> items)             throws IllegalArgumentException, IllegalAccessException {         TestForm form = new TestForm();         for (FileItem item : items) {             if (item.isFormField()) {                 processFormField(form, item);                 continue;             }             form.setDocument(item);         }         return form;     }
    @SuppressWarnings("unchecked")     public static TestForm getTestForm(HttpServletRequest request,             ServletFileUpload handler) throws FileUploadException,             IllegalArgumentException, IllegalAccessException {         return processFileItems(handler.parseRequest(request));     } }
This is a utility class which we use to parse the request object and create ‘TestForm’ class object out of the submitted values. It has two private static methods internally calling others and one public static method, which is the entry point for parsing. We use Commons Bean Utils API to populate the fields of ‘TestForm’ with the values submitted by the user. Lets go through these methods one by one. First the ‘processFormField()’ – this method will be called for each form field found in the request object. It takes two parameters.
  • TestForm form – The form object which we are trying to populate with the submitted values.
  • FileItem item – Form field value we are processing.
This method uses Commons Bean Utils API to populate the given form field in the given form object.  We’ll call the ‘BeanUtils.setProperty()’ method to populate the given field. This method takes three arguments.
  • Object bean – The form object which needs to be populated, in our case its TestForm class object.
  • String name – The Field name to be populated.
  • Object value – The value to set.
Second method in this class is ‘processFileItems()’ – this method will be called once by passing all form values as a ‘java.util.List’. It takes one parameter ‘List<FileItem'>’ which contains all the form fields submitted. We’ll loop through this list and check whether its a simple form field or a file. This ‘org.apache.commons.fileupload.FileItem’ class provides one method ‘isFormField()’ which returns true if the represented field is simple form field, false otherwise. If its a plain form field we’ll call the ‘processFormField()’ and pass necessary parameters to populate the ‘TestForm’ class object. If its not a plain form field, we’ll set it for ‘document’ field in ‘TestForm’ class object by calling ‘setDocument()’ method.
The only public method available in this class is ‘getTestForm()’ – this method will be called from the Servlet to which the form gets submitted. This method takes two parameters – one ‘HttpServletRequest’ object and the other is ‘ServletFileUpload’ class object which is from Commons File Upload API. This object allows us to process the request object and give all the form field values as instances of ‘FileItem’. We dont have to write any code to process the request object, just by calling the ‘parseRequest()’ on this object will give a ‘List’ of ‘FileItem’ object each representing one form field submitted. ‘getTestForm()’ method does nothing more than calling ‘parseRequest()’ method and passing the returned list to ‘processFileItems()’ method. This method in turn returns ‘TestForm’ class object after populating it with the form field values.
Now lets see the Servlet code
package com.rakesh.fileupload.web; 
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.rakesh.fileupload.form.FormUtils; import com.rakesh.fileupload.form.TestForm;
public class FileUploadServlet extends HttpServlet {     private static final long serialVersionUID = 5334402393174853293L;
    private static final String UPLOAD_ERROR = "Error while processing values in request object!";     private static final String FAILURE_MSG = "Error while uploading file!";
    private ServletFileUpload handler;
    @Override     public void init() throws ServletException {         super.init();         DiskFileItemFactory factory = new DiskFileItemFactory();         handler = new ServletFileUpload(factory);     }
    @Override     public void destroy() {         super.destroy();         handler = null;     }
    @Override     protected void doPost(HttpServletRequest request,             HttpServletResponse response) throws ServletException, IOException {         try {             TestForm form = FormUtils.getTestForm(request, handler);             request.setAttribute("DATA", form);         } catch (FileUploadException e) {             e.printStackTrace();             request.setAttribute("ERROR", UPLOAD_ERROR);         } catch (Exception e) {             e.printStackTrace();             request.setAttribute("ERROR", FAILURE_MSG);         }         request.getRequestDispatcher("/WEB-INF/jsp/form-data.jsp").forward(                 request, response);     } }
This ‘FileUploadServlet’ overrides three methods - ‘init()’, ‘destroy()’, and ‘doPost()’. Well you might know that ‘init()’ will be called when the servlet gets initialized, and ‘destroy()’ will be called when the servlet container unloads the servlet. ‘doPost()’ will be called on form submit. As ‘init()’ and ‘destroy()’ are called once in servlet’s lifecycle, they are the best places to initialize resources which are used through out the servlet’s lifecycle. In our case the ‘ServletFileUpload’ object which we’ll be using to parse the request object and get the ‘TestForm’ with submitted form values is being initialized in ‘init()’ method and destroyed in ‘destroy()’ method. Now lets look at the ‘doPost()’ method. This method calls ‘FormUtils.getTestForm()’ method from inside ‘try…catch’ block, this method returns ‘TestForm’ object after populating it with the submitted values. Then we’ll set it as request attribute in the next line, and forward to the ‘form-data.jsp’ page. We’ve two catch blocks one catching ‘FileUploadException’ which will be thrown by the Commons File Upload API’s ‘parseRequest()’ method when it encounters problem parsing the request object. In both the catch blocks we’ll set one error message as request attribute ‘ERROR’ and forward to ‘form-data.jsp’. Well thats all the code we’ve to implement file uploading using Common File Upload API.
If you want to have more form fields, then add them first to the ‘index.jsp’ and then to the ‘TestForm’ class, add corresponding getter/setter methods to those new fields, this is enough have them populated, no other code changes are needed. To display these new fields you might need to change the ‘form-data.jsp’ file. All the files which are part of this example are listed in the below given diagram.
Files list
We need to add three jar files to the application ‘lib’ directory - ‘commons-beanutils-core.jar’, ‘commons-fileupload-1.2.1.jar’ and ‘commons-io-1.4.jar’ which are being used in the example code. I placed ‘form-data.jsp’ in “WEB-INF/jsp” directory, because this page should not accessible directly by typing the URL into the browser address bar. All the files inside ‘WEB-INF’ are not accessible directly for the user, but you can still use them from the servlet – as we did in our servlet.
Please find the links to the source code below in resources section. The ‘file-upload.rar’ file has eclipse project files in it, you can create eclipse project directly from the extracted directory. After creating project from the directory you need to add the ‘servlet-api.jar’ and ‘jsp-api.jar’ to project classpath. The ANT script provided is ready to use, except that you need to update the tomcat server location in it, this is needed to have the ‘servlet-api.jar’ and ‘jsp-api.jar’ in project classpath to compile and build the web application.


Download source code.

Example WAR file.

Apache Tomcat.

Commons File Upload API