[ Team LiB ] Previous Section Next Section

Recipe 8.4 Uploading Multiple Files

Problem

You want to upload more than one file at a time from a client, and handle each file as it is uploaded.

Solution

Use the MultipartParser from Jason Hunter's cos.jar archive.

Discussion

The MultipartParser class allows the servlet to handle each file part sequentially as the server receives a multipart HTTP request.

You can also use the MultipartRequest class to handle multiple files. However, the MultipartParser allows you to handle each part (such as by saving it to a database) during the parsing of a multiple-file upload.


In addition, the file's content type, size, and name can be read as the servlet handles the request. The servlet can also make basic checks using this class, such as counting how many files were uploaded and verifying whether the user uploaded a file for each of the available form input fields.

The HTML file from Recipe 8.5 has been altered to allow the upload of three different files from the user's filesystem, as shown in Figure 8-2.

Figure 8-2. An HTML form for uploading three files
figs/jsjc_0802.gif

This HTML form is created by including three input tags with type="file", as in:

<input type="file" name="file1"><br><br>
<input type="file" name="file2"><br><br>
<input type="file" name="file3">

Example 8-4 handles the multiple file uploads by importing three classes from the cos.jar archive. The MultipartParser class restricts the size of file uploads to 5 MB in Example 8-4; however, you can set this constructor parameter to another value to allow smaller or larger file sizes, or leave the accepted file size at the 1 MB default.

You can view the Javadoc for this class at http://www.servlets.com/cos/javadoc/com/oreilly/servlet/multipart/MultipartParser.html.


The MultipartParser object throws a java.io.IOException if any of the file uploads exceed the size limit. Calling the MultipartParser.readNextPart( ) method returns a Part type, or null if the incoming stream does not contain any more parts. A Part can be either a FilePart or a ParamPart, depending on the content it includes. The ParamPart covers the other parameters that an HTML form might include, such as "username". The FilePart has several methods that provide information about the uploaded file, such as its content type and the filename. The FilePart.writeTo(java.io.File dir) method saves the file to the specified directory and returns the file size as a long type. The FilePart can also write to an OutputStream, as in writeTo(java.io.OutputStream out).

Example 8-4. A servlet handling multiple file uploads
package com.jspservletcookbook;

import javax.servlet.*;
import javax.servlet.http.*;

import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.Part;
import com.oreilly.servlet.multipart.FilePart;

public class ParserServlet extends HttpServlet {
   
    private String fileSavePath;

  public void init( ){
    
      // save uploaded files to a 'data' directory in the web app

      fileSavePath =   getServletContext( ).getRealPath("/") + "data"; 
   
  }
  public void doPost(HttpServletRequest request, 
    HttpServletResponse response) throws ServletException,
      java.io.IOException {

    response.setContentType("text/html");
    java.io.PrintWriter out = response.getWriter( );
    
    out.println("<html>");
    out.println("<head>");
    out.println("<title>File uploads</title>");  
    out.println("</head>");
    out.println("<body>");

    out.println("<h2>Here is information about any uploaded files</h2>");

    try{

        // file limit size of 5 MB
        MultipartParser parser = new MultipartParser(
           request,5 * 1024 * 1024);

        Part _part = null;

        while ((_part = parser.readNextPart( )) != null) {
       
           if (_part.isFile( )) {

               // get some info about the file
               FilePart fPart = (FilePart) _part;
               String name = fPart.getFileName( );
     
               if (name != null) {
  
                   long fileSize = fPart.writeTo(
                     new java.io.File(fileSavePath));

                   out.println("The user's file path for the file: " +
                     fPart.getFilePath( ) + "<br>");

                   out.println("The content type of the file: " +
                     fPart.getContentType( )+ "<br>");

                   out.println("The file size: " +fileSize+ " bytes<br><br>");

                  //commence with another file, if there is one

               } else {
  
               out.println(
                 "The user did not upload a file for this part.");

               }

          }    else if (_part.isParam( )) {
              // do something else if it is a non-file-type parameter,
              //such as a username
          }
  
        }// end while


        out.println("</body>");
        out.println("</html>");

    } catch (java.io.IOException ioe){
       
       //an error-page in the deployment descriptor is 
       //mapped to the java.io.IOException
        throw new java.io.IOException(
            "IOException occurred in: " + getClass( ).getName( ));
    }
    }//doPost

    public void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException,
        java.io.IOException {
        
        throw new ServletException(
            "GET method used with " + getClass( ).getName( )+
                 ": POST method required.");
    }
}

Figure 8-3 shows the descriptive page that the servlet displays about each uploaded file.

Figure 8-3. A servlet displays information about uploaded files
figs/jsjc_0803.gif

See Also

Recipe 8.1 on preparing the HTML for a file upload; Recipe 8.4 on downloading and using the com.oreilly.servlet library; Recipe 8.5 on handling a single file upload in a servlet; Recipe 8.5 on controlling file naming; Recipe 8.6 on using a JSP to handle file uploads; the homepage for com.oreilly.servlet: http://www.servlets.com/cos/index.html; the RFC 1867 document on form-based file uploads: http://www.ietf.org/rfc/rfc1867.txt.

    [ Team LiB ] Previous Section Next Section