Search This Blog

Saturday 27 February 2016

Servlet 3.x - Using MultipartConfig for file uploads

In an earlier post, I had written on performing file upload and download using Spring MVC. In that example I used commons-fileupload-1.2.2.jar. This is because Servlets did not have built in support for File upload operation. However Servlets 3.x provides support - as a part of the specs. So no need to include any additional jars. I decided to try an example of the same.
First step was to add an HTML form:
<html>
<head></head>
<body>
   <form action="upload.upl" method="post" enctype="multipart/form-data">
      Enter Player Name: &nbsp;&nbsp;&nbsp; 
      <input type="text" name="playerName" /> <br /> 
      Select File(s) to Upload: 
      <input type="file" name="file1Name"> <br /> 
      <input type="file" name="file2Name"> <br /> 
      <input type="file" name="file3Name"> <br /> 
      <input type="submit" value="Upload">
   </form>
</body>
</html>
The form accepts three files and a text field. The form type is multipart/form-data which indicates a form capable of sending simple data as well as files.
The enctype attribute indicates the encoding used. Its default value is application/x-www-form-urlencoded which is what we use in our simple forms. To process the form I created an upload servlet:
@SuppressWarnings("serial")
@WebServlet(displayName = "FileUploadServlet", 
  description = "Servlet for FileUpload Operations", urlPatterns = { "*.upl" })

@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 10, // 10 MB
maxFileSize = 1024 * 1024 * 25, // 25 MB
maxRequestSize = 1024 * 1024 * 50) // 50 MB
public class FileUploadServlet extends HttpServlet {
The new annotation introduced here is the MultipartConfig.As described by Java docs:
Annotation that may be specified on a Servlet class, indicating that instances 
of the Servlet expect requests that conform to the multipart/form-data MIME type.
I added the code to process the post request of the form in the doPost method:
  /**
   * Directory where uploaded files will be saved, its relative to the web
   * application directory.
   */
  private static final File UPLOAD_DIRECTORY = new File("E:\\temp");

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Get all the parts from request and write it to the file on server

    // 1: Return a collection of all uploaded Parts.
    Collection<Part> allUploadedParts = request.getParts();
    int i = 0;
    for (Part part : allUploadedParts) {
      // Part: class represents a part as uploaded to the server as part of a
      // multipart/form-data request body. The part may represent either an
      // uploaded file or form data.

      // 2: Retain only file parts and not any form parts
      // Get name of File
      String fileName = part.getSubmittedFileName();
      if (fileName == null)
        continue;

      // 3: Write the file to the disk
      // convenience method to write an uploaded part to disk.
      part.write(UPLOAD_DIRECTORY + File.separator + fileName);
      i++;
    }
    String playerName = request.getParameter("");
    playerName = playerName != null && !"".equals(playerName.trim())
        ? playerName.toUpperCase() : " UNKNOWN ";

    response.getWriter()
        .write(playerName + " has " + i + " File(s) uploaded successfully!");
    response.getWriter().flush();
  }
The code can be explained as below:
  1. The getParts method gets all the Part components of this request, provided that it is of type multipart/form-data. Parts include both files and form inputs.
  2. The getSubmittedFileName method of Part will be null for file fields.
  3. The last method I used here is the write method - which will write the file contents to the directory specified as a file.
I ran the request against a Tomcat server

On completion:
The Multipart configuration can also be placed in the XML file - making it easier to increase/decrease
<servlet>
      <description></description>
      <display-name>WelcomeServlet</display-name>
      <servlet-name>WelcomeServlet</servlet-name>
      <servlet-class>com.servlets.WelcomeServlet</servlet-class>
      <multipart-config>
         <location>/tmp</location>
         <max-file-size>208480</max-file-size>
         <max-request-size>418841</max-request-size>
         <file-size-threshold>1066476</file-size-threshold>
      </multipart-config>
   </servlet>

1 comment: