Wednesday 27 June 2012

FileUpload using Servlet 3.0

Servlet 3.0 container's has standard support for multipart data. If a request Content-Type is multipart/form-data and the MultiPartConfig is configured on the servlet,  the HttpServletRequest makes the parts available using Servlet 3.0 newly added methods in HttpServletRequest.

First, lets see the new API available in Servlet 3.0 :

javax.servlet.http.HttpServletRequest (API Documentation)

  • Collection<Part> getParts()
  • Part getPart(String partName)

javax.servelt.Part (API Documentation)

  •  void  delete()                                               
  •  String  getContentType()                 
  •  String  getHeader(String name)                                                              
  •  Collection<String>  getHeaderNames() 
  •  Collection<String>  getHeaders(String name) 
  •  InputStream  getInputStream()                       
  •  String  getName()                                        
  •  long  getSize()       
  •  void  write(java.lang.String fileName)  
Lets us try to understand the API by writing an example.

The  first thing in this example is the upload page. This is how it looks:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Upload </title></head>
<body>
<form action="uploadservlet" method="post" enctype="multipart/form-data">
    Name :<input type="text" name="name"/><br>
    Age :<input type="text" name="age"/><br>
    Upload Photo:<input type="file" name="photo"/><br>
    <input type="submit"/>
</form>
</body>
</html>

Next is implementing the Upload Servlet. Here is how it looks:

@MultipartConfig(location = "D:\\images", maxFileSize = 102400, maxRequestSize = 204800,

                          fileSizeThreshold = 1024)
@WebServlet(name = "UploadServlet",urlPatterns = "/uploadservlet")public class UploadServlet extends HttpServlet
{
    protected void service(HttpServletRequest request,
                           HttpServletResponse response) throws ServletException, IOException
    {
        Collection<Part> parts = request.getParts();
        for (Part part : parts) {
            System.out.println("" + part.getName());
        }
        System.out.println(parts.size());
        if (parts.size() != 3) {
            response.sendError(500, "All Fields are mandatory. ");
        }

        Part filePart = request.getPart("photo");
        //read imageInputStream if required
        InputStream imageStream = filePart.getInputStream(); 
        
        //can also write the photo to local storage
        filePart.write("users/photo.jpg");
        filePart.delete(); //deletes the underlying storage if used

        //Read name, String Type
        Part namePart = request.getPart("name");
        //Part.getSize() returns the length of the individual part
        if (namePart.getSize() > 20) {
            //write name cannot exceed 20 chars
            response.sendError(500, "Name cannot exceed 20 chars");
        }
        //name , String type can also obtained using Request parameter
        String nameParameter = request.getParameter("name");

        int ageParameter = Integer.parseInt(request.getParameter("age"));

        response.getWriter().print("Welcome, " + nameParameter + "!. Your age is " + ageParameter);

    }

}


We will now discuss the above example in detail.

The HttpServletRequest will make the parts available using the getPart(..) and getParts() methods only if the MultiPartConfig is defined for that Servlet. It can be done in two ways:
  • Using @MultiPartConfig annotation 
  • In web.xml, by adding <multipart-config> entry inside <servlet> definition.
        <servlet>
           <servlet-name>UploadServlet</servlet-name>
           <servlet-class>com.fileupload.UploadServlet</servlet-class>
           <multipart-config>
               <file-size-threshold>1024</file-size-threshold>
               <location>D:\\images</location>
               <max-file-size>102400</max-file-size>
               <max-request-size>204800</max-request-size>
           </multipart-config>
        </servlet>

Lets discuss the properties MultiPartConfig has in details. These properties can be defined both for Annotation and in web.ml.
  • file-size-threshold/fileSizeThreshold : The size beyond which the file is written to temporary file in disk.
  • location : The location where the parts written using Part.write() will be stored.
  • max-file-size/maxFileSize: The maximum size allowed for uploaded file.
  • max-request-size / maxRequestSize :  The maxim size allowed for multipart/form-data requests.