Ajax file upload to a Java Servlet in HTML5

HTML5 comes with a great feature which is the ability to upload files using the XMLHttpRequest version 2.
Modern Gecko and WebKit browsers include a wonderful object FormData that allows combining both simple and complex form data (text and files) in the Ajax request object.

Let's show you how to do this.

In the example, we are having a form with two fields, one field represents a simple text field, and the other one represents a file field as shown in the code below.

<form id="form1">    

    <label for="sampleText">Please enter a text</label>

    <input id="sampleText" name="sampleText" type="text" /> <br/>

    <label for="sampleFile">Please select a file

    <input id="sampleFile" name="sampleFile" type="file" /> <br/>

    <input id="uploadBtn" type="button" value="Ajax Submit" onClick="performAjaxSubmit();"></input>

</form>

<script type="text/javascript">

    function performAjaxSubmit() {

        var sampleText = document.getElementById("sampleText").value;

        var sampleFile = document.getElementById("sampleFile").files[0];

        var formdata = new FormData();

        formdata.append("sampleText", sampleText);

        formdata.append("sampleFile", sampleFile);

        var xhr = new XMLHttpRequest();       

        xhr.open("POST","/fileUploadTester/FileUploader", true);

        xhr.send(formdata);

        xhr.onload = function(e) {

            if (this.status == 200) {

               alert(this.responseText);

            }

        };                    

    }   

</script>

As we see in the listed code, it is a normal old XHR code, but it has two differences:
1. The files property in the HTML5 input file, which gives you the ability to get the file(s) object(s).
2. The FormData object, which has one method called append, that allows adding any form data (text and file) to the object. The FormData object has another big advantage which is making the Ajax request “multipart/form-data” without writting any special code.

Now, Let's move to the Servlet code (Iam using Apache Commons File Upload for handling the multipart form request parsing).

public class FileUploader extends HttpServlet {

    protected void doPost(HttpServletRequest request,

                          HttpServletResponse response)

                          throws ServletException, IOException {

        String ajaxUpdateResult = "";

        try {

            List items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);            

            for (FileItem item : items) {

                if (item.isFormField()) {

                    ajaxUpdateResult += "Field " + item.getFieldName() + 

                    " with value: " + item.getString() + " is successfully read\n\r";

                } else {

                    String fileName = item.getName();

                    InputStream content = item.getInputStream();

                    response.setContentType("text/plain");

                    response.setCharacterEncoding("UTF-8");

                    // Do whatever with the content InputStream.

                    System.out.println(Streams.asString(content));

                    ajaxUpdateResult += "File " + fileName + " is successfully uploaded\n\r";

                }

            }

        } catch (FileUploadException e) {

            throw new ServletException("Parsing file upload failed.", e);

        }

        response.getWriter().print(ajaxUpdateResult);

    }
}

The Servlet simply parses the multipart form request and then constructs a message with the result.

Please keep in mind that this code will work with Chrome 5 and Safari 5, Firefox 4 but unfortunately will not work with IE9 because miserably IE9 does not have the FormData object, I will show later how you can achieve the same behaviour in IE9 “Iam sure you will not like it because it is much harder ;-)”.

Download the complete code from here.

This entry was posted in HTML5, Java, JavaScript and tagged , , , , , by hazems. Bookmark the permalink.

About hazems

Hazem Saleh has more than eleven years of experience in Cloud, Mobile and Open Source technologies. He worked as a software engineer, technical leader, application architect, and technical consultant for many clients around the world. He is an Apache PMC (Project Management Committee) member and a person who spent many years of his life writing open source software. Beside being the author of the "JavaScript Unit Testing" book, "JavaScript Mobile Application Development" book, "Pro JSF and HTML5" book and the co-author of the "Definitive guide to Apache MyFaces" book, Hazem is also an author of many technical articles, a developerWorks contributing author and a technical speaker in both local and international conferences such as ApacheCon North America, Geecon, JavaLand, JSFDays, CON-FESS Vienna and JavaOne. Hazem is an XIBMer, he worked in IBM for ten years. Now, He is working for Nickelodeon New York as a Mobile Architect. He is also an OpenGroup Master Certified Specialist.

4 thoughts on “Ajax file upload to a Java Servlet in HTML5

  1. Thank you for the example.
    Can you please explain also the IE solution/problem/?

    “I will show later how you can achieve the same behaviour in IE9”

    Thanks

  2. This is my source code. I want to pass string value to servlet using FormData.
    my IDE is netbeans 7.2 Beta

    function sendForm() {
    alert(‘asdf’);
    var formData = new FormData();
    formData.append(‘username’, ‘johndoe’);
    formData.append(‘id’, 123456);

    var xhr = new XMLHttpRequest();
    xhr.open(‘POST’, ‘getVal’);
    //xhr.onload = function(e) { … };

    xhr.send(formData);

    xhr.onload = function(e) {

    if (this.status == 200) {

    alert(this.responseText);

    }else{
    alert(‘asdfaaa’);
    }

    }

    }

    Full name:

    Email address:

    Repeat email address:

    Arrival date:

    Number of nights (rooms are $99.00 per night):

    Number of guests (each additional guest adds $10.00 per night):

    Estimated total:
    $99.00

    Promo code:

    function check(input) {
    if (input.value != document.getElementById(’email_addr’).value) {
    input.setCustomValidity(‘The two email addresses must match.’);
    } else {
    // input is valid — reset the error message
    input.setCustomValidity(”);
    }
    }

    and my servlet source code is:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.Part;

    /**
    *
    * @author db2admin
    */
    @WebServlet(name = “getVal”, urlPatterns = {“/getVal”})
    @MultipartConfig
    public class getVal extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    response.setContentType(“text/html;charset=UTF-8”);
    PrintWriter out = response.getWriter();
    try {

    out.println(“inside servlet… “);

    Part name = request.getPart(“username”);

    String name1=getValue(name);

    out.println(“name “+name1);

    } finally {
    out.close();
    }
    }

    private static String getValue(Part part) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), “UTF-8”));
    StringBuilder value = new StringBuilder();
    char[] buffer = new char[1024];
    for (int length = 0; (length = reader.read(buffer)) > 0;) {
    value.append(buffer, 0, length);
    }
    return value.toString();
    }

    }

  3. I have used this code with struts2.0. but parseRequest(request) is not working in that action class of struts2.0, Can you please tell me about that.

Comments are closed.