File upload using Apache open source class libraries in Servlet

With specific examples, this paper describes how to upload files in Servlet s using packages provided by the Apache open source class library.The reference book for this article is the third edition of Tomcat and Java Web Development Technical Details by Sun Weiqin.

The software versions used in this paper are: Window10, JDK10, Tomcat9.
The Download Web address for the source code covered in this article is:
http://www.javathinker.net/javaweb/upload-app.rar

The Apache Open Source Software Organization provides two packages related to file uploads:
Fileupload Package (commons-fileupload-X.jar): Package responsible for uploading files, download at: http://commons.apache.org/fileupload/.
The web address of the instructions for using the package is: http://commons.apache.org/fileupload/using.html.
I/O Package (commons-io-X.jar): Package responsible for input and output, download at: http://commons.apache.org/io/.

JAR files for both packages should be placed in the helloapp/WEB-INF/lib directory.These two JAR files are already available in the sourcecode/chapter05/helloapp/WEB-INF/lib directory of the accompanying source code package for this book.Servlet s mainly use the interfaces and classes in the fileupload package to upload files, while the fileupload package itself relies on the I/O package.Figures 1-1 below are class diagrams of the major interfaces and classes in the fileupload package.


Figure 1-1 Class block diagrams of major interfaces and classes in the fileUpload package

As shown in Figures 1-2 below, for an HTTP request with a body part of the type "multipart/form-data", the uploadfile package treats each subpart of the composite form contained in the request body as a FileItem object.There are two types of FileItem objects:
formField: Common form field types, text fields in forms, submit buttons, etc. are all of this type.
Non-formField: Upload file type, which is the file field in the form that contains file data.


Figure 1-2 Each subpart of the composite form is treated as a FileItem object

FileItemFactory is the factory where FileItem objects are created.The DiskFileItemFactory and DiskFileItem classes implement the FileItemFactory and FileItem interfaces, respectively.The DiskFileItem class represents a hard disk-based FileItem that can save file data uploaded by the client to the hard disk.DiskFileItemFactory is the factory where DiskFileItem objects are created.
The following program code creates a DiskFileItemFactory object and then sets the size of the buffer used to write data to the hard disk and the temporary directory used.In the implementation of the fileupload package itself, to improve the efficiency of writing data to the hard disk, especially to large volumes of data, the fileupload package uses a cache when writing data and stores some temporary data to a temporary directory.

//Create a hard disk-based FileItem factory
DiskFileItemFactory factory = new DiskFileItemFactory();
//Set the size of the buffer used to write data to the hard disk, where 4K
factory.setSizeThreshold(4*1024); 
//Set Temporary Directory
factory.setRepository(new File(tempFilePath));

The ServletFileUpload class is a file upload processor that is associated with FileItemFactory.The following program code creates a ServletFileUpload object that is associated with a DiskFileItemFactory object.The setSizeMax() method of the ServletFileUpload class is used to set the maximum size of files that are allowed to be uploaded.

//Create a file upload processor
ServletFileUpload upload = new ServletFileUpload(factory);
//Set the maximum file size allowed to upload, 4M here
upload.setSizeMax(4*1024*1024); 

The parseRequest(HttpServletRequest req) method of the ServletFileUpload class parses the composite form data in the HttpServletRequest object and returns a List collection containing a set of FileItem objects:

List<FileItem> items = upload.parseRequest(request);

Once you have a List collection containing FileItem objects, you can iterate through it, determine the type of each FileItem object, and then process it accordingly.

for(FileItem item:items){  //Traverse through each FileItem object in the collection
  if(item.isFormField()) {
    processFormField(item,out); //Working with common form fields
  }else{
    processUploadedFile(item,out); //Processing uploaded files
  }
}

The UploadServlet class of routines 1-1 below uses the fileupload package to process files that users upload on the upload.htm page.

Routine 1-1 UploadServlet.java

package mypack;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.fileupload.disk.*;

public class UploadServlet extends HttpServlet {
  private String filePath; //Directory to store uploaded files
  private String tempFilePath; //Directory to store temporary files

  public void init(ServletConfig config)throws ServletException {
    super.init(config);
    filePath=config.getInitParameter("filePath");
    tempFilePath=config.getInitParameter("tempFilePath");
    filePath=getServletContext().getRealPath(filePath);
    tempFilePath=getServletContext().getRealPath(tempFilePath);
  }
  public void doPost(HttpServletRequest request,
         HttpServletResponse response)
         throws ServletException, IOException {
    response.setContentType("text/plain");
    //Send response body to client
    PrintWriter out=response.getWriter(); 
    try{
      //Create a hard disk-based FileItem factory
      DiskFileItemFactory factory = new DiskFileItemFactory();
      //Set the size of the buffer used to write data to the hard disk, where 4K
      factory.setSizeThreshold(4*1024); 
      //Set Temporary Directory
      factory.setRepository(new File(tempFilePath));

      //Create a file upload processor
      ServletFileUpload upload = new ServletFileUpload(factory);
      //Set the maximum file size allowed to upload, 4M here
      upload.setSizeMax(4*1024*1024); 

      List<FileItem> items = upload.parseRequest(request);    

      for(FileItem item:items){
        if(item.isFormField()) {
          processFormField(item,out); //Working with common form fields
        }else{
          processUploadedFile(item,out); //Processing uploaded files
        }
      }
      out.close();
    }catch(Exception e){
       throw new ServletException(e);
    }
  }

  private void processFormField(FileItem item,PrintWriter out){
    String name = item.getFieldName();
    String value = item.getString();
    out.println(name+":"+value+"\r\n");
  }

  private void processUploadedFile(FileItem item,
               PrintWriter out)throws Exception{
    String filename=item.getName();
    int index=filename.lastIndexOf("\\");
    filename=filename.substring(index+1,filename.length());
    long fileSize=item.getSize();

    if(filename.equals("") && fileSize==0)return;

    File uploadedFile = new File(filePath+"/"+filename);
    item.write(uploadedFile);
    out.println(filename+" is saved.");
    out.println("The size of " +filename+" is "+fileSize+"\r\n");
  }

The configuration code for the UploadServlet in the web.xml file is as follows:

<servlet>
  <servlet-name>upload</servlet-name>
  <servlet-class>mypack.UploadServlet</servlet-class>
  <init-param>
    <param-name>filePath</param-name>
    <param-value>store</param-value>
  </init-param>
  <init-param>
    <param-name>tempFilePath</param-name>
    <param-value>temp</param-value>
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>upload</servlet-name>
  <url-pattern>/upload</url-pattern>
</servlet-mapping>

The UploadServlet has two initialization parameters: the filePath parameter represents the directory where the UploadServlet will store the uploaded files, and the tempFilePath parameter represents the directory where the fileupload package will store the temporary files.

The upload.htm routines 1-2 below define a composite form for uploading files, which has a text field named "username" and two file fields for specifying the file to upload.

Routine 1-2 upload.htm

<html>
<head>
<title>Upload</title>
</head>
<body >
  <form name="uploadForm" method="POST"
    enctype="MULTIPART/FORM-DATA"
    action="upload">
    <table>
      <tr>
       <td><div align="right">User Name:</div></td>
       <td><input type="text" name="username" size="30"/> </td>
      </tr>
      <tr>
       <td><div align="right">Upload File1:</div></td>
       <td><input type="file" name="file1" size="30"/> </td>
      </tr>
      <tr>
        <td><div align="right">Upload File2:</div></td>
        <td><input type="file" name="file2" size="30"/> </td>
      </tr>
      <tr>
        <td><input type="submit" name="submit" value="upload"></td>
        <td><input type="reset" name="reset" value="reset"></td>
      </tr>
    </table>
  </form>
</body>

</html>

Accessing http://localhost:8080/helloapp/upload.htm from a browser will bring up the HTML page shown in Fig. 1-3.

Figure 1-3 upload.htm page

For the upload.htm page in Fig. 1-3, provide the data shown in the diagram in the form, and submit the form. Upload Servlet responds to this request by saving both the FromClient.rar and FromClient.txt files to the helloapp/store directory and returning the HTML page shown in Fig. 1-4 to the client.

Figure 1-4 HTML page returned by UploadServlet

UploadServlet calls the setSizeMax(410241024) method of the ServletFileUpload object to set the maximum file size allowed to upload to 4M.If you enter a file larger than 4M in the upload.htm page in Fig. 1-3, the Upload Servlet will throw the following exception when processing the upload file:

org.apache.commons.fileupload.FileUploadBase
$SizeLimitExceededException: 
the request was rejected because its size (7859197) 
exceeds the configured maximum (4194304) 

Keywords: Java Apache Tomcat Web Development

Added by mazzzzz on Thu, 27 Jun 2019 19:15:44 +0300