OOP-ResearchMake It Simpler by Object Oriented Programming

Apache Tomcat, multipart/form-data, file upload, Servlets, JSP

File upload patch for multipart/form-data on Apache Tomcat. JSP or Servlets on Apache Tomcat can accept multipart/form-data for file upload. This is beyond the current Servlet Specification, but Apache Tomcat may be more useful. You can create file upload Servlets and JSP on Apache Tomcat.


This patch does not work on Tomcat 3.2 and later. Instead, please try OOP MimeParser, that will run on any Servlet container.

1: What is Tomcat

As you know, JSP and Servlet plays the role of the user interface of J2EE applications. I'm sure that the serious system developers in the world are desire for the cool servlet server. And now, Tomcat is available.
Tomcat3.1 is the implementation of JavaServerPages1.1 and Servle2.2 specification and developed and maintained by the Jakarta Project.

Go Site Map

2: Tomcat can receive MIME data! (Un-official extension)

Tomcat may be more useful if it can receive the POST data with 'multipart/form-data' in addition to the POST data with 'application/x-www-form-urlencoded'.
The POST data with 'multipart/form-data' is posted via the FORM like:

<FORM ACTION="http://foo.com/bar.jsp" METHOD=POST
      ENCTYPE="multipart/form-data">
<BR>
Please input some text:
<BR>
	<INPUT TYPE=text NAME=text_1>
<BR>
Please choose file:
<BR>
	<INPUT TYPE=file NAME=file_1>
<BR>
Please another choose file:
<BR>
	<INPUT TYPE=file NAME=file_2>
<BR>
	<INPUT TYPE=submit VALUE="Submit">
</FORM>
And the stream sent from the WWW browser to the HTTP server is described in HTML4.0 Specification. As you see, the client user can upload multiple files to the HTTP server at a time.
Because this is the beyond the current Servlet Specification (v2.2), the servlet writer have to use use some server dependent classes and this means such a servlet cannot be deployed into other servlet server. If this is OK, try my extension.
This function have been discussed in the Tomcat developer mailing list, and the future version of Tomcat may implement this. But for your convenience, I modified and appended some classes and uploaded their source. They are:
  • Modified class
    1. org.apache.tomcat.core.ContextManager
    2. org.apache.tomcat.core.RequestImpl
    3. org.apache.tomcat.core.Request
    4. org.apache.tomcat.core.RequestInterceptor
    5. org.apache.tomcat.core.BaseInterceptor
    6. org.apache.tomcat.core.HttpServletRequestFacade
  • Appended class
    1. com.oopreserch.tomcat.request.ParseMime
    2. com.oopreserch.tomcat.util.PostDataSource
    3. com.oopreserch.tomcat.util.MimeFile
    4. com.oopreserch.tomcat.util.CharsetToJavaEnc
The main class of this extension, ParseMime, writes the bytes of uploaded files onto the disk cash. ParseMime is the subclass of BaseInterceptor and overrides:
    public void engineShutdown(ContextManager cm)
	throws TomcatException;
This methods deletes all the cash files when Tomcat shutdown.
The path of each disk cash follows the rule below:
  1. Directory is retrieved from ContextManager.getWorkDir()
  2. File name is NAME_OF_ORIGINAL_FILE+((new Date().getTime())
All the absolute paths to the disk cash after the startup are recorded and the actual files are deleted on shutdown.
The servlet developers can get the content of the uploaded files through MimeFile class. MimeFile is the simple class which holds the actual file name and the path to the disk cash. We can access the original file name and the contents of the uploaded file via the following methods:
    public String getFileName();

    public InputStream getInputStream();

    public byte[] getBody();

    public String getContentType();

The 'getBody()' methods read the content of the disk cash and returns the byte[].
The servlet developers can retrieve MimeFile objects through 'HttpServletRequestFacade', not the 'ServletRequest' interface. So the servlet must be dependent on Tomcat and cannot be deployed into other server.
The following methods are now available on 'HttpServletRequestFacade':
    public MimeFile getFile(String name);

    public MimeFile[] getFileValues(String name);
    
    public Enumeration getFileNames();
The instance of 'HttpServletRequestFacade' is retrieved by casting HttpServletRequest. It looks like this:
    public void doPost(HttpServletRequest req,
                       HttpServletResponse res)
	throws ServletException, IOException {

	HttpServletRequestFacade rf=
            (HttpServletRequestFacade)req;
	Enumeration files=rf.getFileNames();
	if(files.hasMoreElements()){
	    String p_name=(String)(files.nextElement());
	    MimeFile[] mimes=rf.getFileValues(p_name);
	    String c_type=mimes[0].getContentType();
	    res.setContentType(c_type);    
	    ServletOutputStream out=
                res.getOutputStream();
	    out.write(mimes[0].getBody());
	}
    }

As you guess, this servlet just returns the uploaded file (if the multiple files are uploaded, the first one) back to the client.
ParseMime and related classes uses Java Mail API to parse the uploaded data, so please download it. For details about JavaMail API, see: http://java.sun.com/products/javamail/index.html
NOTE:
Of course, I've posted these sources to the Tomcat developer mailing list. But they are not necessarily adopted as they are, and the future version of Tomcat will include more optimized class based on the farther discussion of the mailing list. In this point, the classes above are UN-OFFICIAL ones.

You can download my source distribution here.

Go Site Map

This patch does not work on Tomcat 3.2 and later. Instead, please try OOP MimeParser, that will run on any Servlet container.

3: Compiling the modified classes and helper classes

Download my distribution and extract it. When extracted, the directory 'tomcat_oop_mime' is created. Please confirm that 'CLASSPATH'(which includes the jar files required for Java Mail API and Java Activation API) and 'TOMCAT_HOME' environment variables are set properly. Change to the directory of 'tomcat_oop_mime' and execute the shell script named 'build_oop.sh'. This script compiles the updated class and my helper class, and then updates the '$TOMCAT_HOME/lib/webserver.jar' file.

Go Site Map

4: Configuration

In $TOMCAT_HOME/conf/server.xml, com.oopreserch.tomcat.request.ParseMime should be specified. To decode parameter string properly, this helper class adapts the 'option A' of My Proposal to Servlet and JSP Specification, so you need to supply the charset in which the parameter string is encoded. It looks like this:

<RequestInterceptor
    className="com.oopreserch.tomcat.request.ParseMime"
    Charset="Shift_JIS" FileUpper="50000" />
The 'FileUpper' means the maximum size of file (in bytes) which can be uploaded. Note that without 'FileUpper', any size of file can be uploaded.

Go Site Map

Caution!
All the APIs for Servlet/JSP introduced by this web site are now included in Bento framework:
  • Simpler than JSTL or Apache Struts
  • MVC framework by HTML
  • Input validation from CGI FORM
  • Easy user authentication
  • Easy localization (L10n)
To download the APIs and source code examples, please visit the web site of Bento framework.


JBuilder 2007


General Information

For Java Development

Java and all Java-based trademarks and logos are trademarks or registered of Sun Microsystems, Inc. in the United States and other countries.


ALL CONTENTS COPYRIGHT 1997-2007, OOP-Research Corporation. All rights reserved.