[ Team LiB ] Previous Section Next Section

Recipe 8.6 Using a JSP to Handle a File Upload

Problem

You want to use a JSP to handle a file upload.

Solution

Create a JavaBean that wraps the functionality of the com.oreilly.servlet.MultipartRequest class from Jason Hunter's cos.jar library. Then use the jsp:useBean standard action in a JSP to create an instance of this bean for handling the file uploads.

Discussion

This recipe describes a JavaBean that uses the com.oreilly.servlet.MultipartRequest class to manage file uploads. First, I'll show the bean that wraps the functionality of the MultipartRequest class, then the JSP that uses the bean to upload a file.

Example 8-6 shows the UploadBean used by the JSP in Example 8-7.

Example 8-6. A file-uploading JavaBean
package com.jspservletcookbook;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletRequest;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

public class UploadBean {
   
    private String webTempPath;
    private HttpServletRequest req;
    private String dir;
    
public UploadBean( ) {}

  public void setDir(String dirName) {

      if (dirName == null || dirName.equals(""))
        throw new IllegalArgumentException(
           "invalid value passed to " + getClass( ).getName( )+".setDir");

      webTempPath = dirName;

  }

  public void setReq(ServletRequest request) {

      if (request != null && request instanceof HttpServletRequest){

          req = (HttpServletRequest) request;

      } else {
  
          throw new IllegalArgumentException(
            "Invalid value passed to " + getClass( ).getName( )+".setReq");
      }

  }
    
  public String getUploadedFiles( ) throws java.io.IOException{
   
      //file limit size of 5 MB
      MultipartRequest mpr = new MultipartRequest(
        req,webTempPath,5 * 1024 * 1024,new DefaultFileRenamePolicy( ));

      Enumeration enum = mpr.getFileNames( );

      StringBuffer buff = new StringBuffer("");
        
      for (int i = 1; enum.hasMoreElements( );i++){

            buff.append("The name of uploaded file ").append(i).
              append(" is: ").
                append(mpr.getFilesystemName((String)enum.nextElement( ))).
                  append("<br><br>");
      }//for
        
      //return the String
      return buff.toString( );

  } // getUploadedFiles

}

This code imports the classes it needs to handle the uploaded files with the MultipartRequest class. The DefaultFileRenamePolicy class is used in the MultipartRequest constructor to handle conflicts between the names of uploaded files and any existing files with the same name. When these naming conflicts occur, the DefaultFileRenamePolicy class automatically adds a number to the end of the uploaded file, as in index1.txt if the uploaded file was named index.txt.

Example 8-6 uses the JavaBean naming conventions for its methods, as in setDir( ) and getUploadedFiles( ), which allow the methods to be called using the jsp:getProperty and jsp:setProperty standard actions. Example 8-7 shows the use of both of these actions and the JSP that handles the file upload and display information about the uploaded files.

The JSP uses the UploadBean, the class I just defined. The JSP instantiates the bean using the jsp:useBean standard action, sets the directory name where the uploaded file will be saved with jsp:setProperty, then uses jsp:getProperty to save the file(s) to the specified directory.

Example 8-7. A JSP that uploads files and displays information about them
<jsp:useBean id="uploader" class="com.jspservletcookbook.UploadBean" />

<jsp:setProperty name="uploader" property="dir"
    value="<%=application.getInitParameter(\"save-dir\")%>" />

<jsp:setProperty name="uploader" property="req"  value="<%= request %>" />

<html>
<head><title>file uploads</title></head>
<body>
<h2>Here is information about the uploaded files</h2>

<jsp:getProperty name="uploader" property="uploadedFiles" />

</body>
</html>

The JSP in Example 8-7 creates an instance of the UploadBean with this code:

<jsp:useBean id="uploader" class="com.jspservletcookbook.UploadBean" />

The com.jspservletcookbook.UploadBean class must be placed in the web application's WEB-INF/classes directory (inside of WEB-INF/classes/com/jspservlet/cookbook), or in a JAR file inside of WEB-INF/lib.


The JSP then passes the HttpServletRequest object to the bean with this code:

<jsp:setProperty name="uploader" property="req" value="<%= request %>" />

Under JSP 2.0, you can pass along the request value with this code:

<jsp:setProperty name="uploader" property= "req"  value="${pageContext.request}" />

The JSP 2.0 specification allows the use of EL syntax in the jsp:setProperty value attribute.


The bean needs the request object to pass into the MultipartRequest constructor, which does all the file-uploading work. The JSP also specifies the directory where uploaded files are saved:

<jsp:setProperty name="uploader" property="dir"
    value="<%=application.getInitParameter(\"save-dir\")%>" />

The expression application.getInitParameter(\"save-dir\") returns the value of the context parameter save-dir, which is the path to the directory where the uploaded files are saved. Here is what this web.xml element looks like:

<!-- beginning of deployment descriptor -->
<context-param>
    <param-name>save-dir</param-name>
    <param-value>h:\home\data</param-value>
</context-param>
<!-- deployment descriptor continues -->

The final step is to call the bean's getUploadedFiles( ) method. The JSP accomplishes this task using the jsp:getProperty standard action, as in:

<jsp:getProperty name="uploader" property="uploadedFiles" />

The JSP can call the bean's method in this manner, as though the JSP was fetching a bean property, because I named the method with the standard "get" prefix: getUploadedFiles( ). Tricky!


Figure 8-4 shows the resulting web page after the user has submitted the HTML form.

Figure 8-4. A JSP that handles file uploads
figs/jsjc_0804.gif

To use this JSP to handle a file upload, you have to specify it in an HTML form tag's action attribute, as in:

<form action="http://localhost:9000/home/upload.jsp" method="post" 
enctype="multipart/form-data">

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.3 and Recipe 8.6 on handling single- and multiple-file uploads in a servlet; Recipe 8.5 on controlling file renaming as files are uploaded; 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