4. Handling Form-based
File Upload with Java Servlet or JSP
Unlike
PHP, Java Servlet and JSP do not have build-in mechanisms for
handling form-based file uploads. One solution to this problem is to
implement a function yourself to extract uploaded files contained in
an HTTP request. However, a better choice is to make use of a
third-party library that can help us handle file uploads.
One
robust library available is the Apache Jakarta Commons FileUpload
package. It is open-source and can be downloaded free of charge over
the Internet. We will demonstrate how to use the Apache Jakarta
Commons FileUpload package to extract uploaded files submitted from a
form. The techniques are the same for HTML and XHTML. If you are not
familiar with JSP or Java Servlet, you may want to read some
introductory tutorials before going through this section.
At
the time of writing, the most up-to-date version of the Apache
Jakarta Commons FileUpload library is 1.1.1. So, we assume you are
using Commons FileUpload 1.1.1 in this tutorial. For other versions
of Commons FileUpload, the procedures may be slightly different but
the principle is the same.
4.1. Downloading the
Apache Jakarta Commons FileUpload and Commons IO Libraries
To
download the Apache Jakarta Commons FileUpload library, go to the
home page of the Apache
Jakarta Commons FileUpload project and navigate to the download
section. The binaries are available in two file formats: zip format
and tar-gzip format. Download either one of them and uncompress the
file. Then go to the home page of the Apache
Jakarta Commons IO project and repeat the same steps. We need the
Commons IO library since Commons FileUpload uses it internally. Now
you have two JAR files, "commons-fileupload-version.jar"
and "commons-io-version.jar", where version
is the version number. At the time of writing, the latest version of
the Commons FileUpload library and that of the Commons IO library are
1.1.1 and 1.2 respectively. So, the JAR files we obtain are
"commons-fileupload-1.1.1.jar" and "commons-io-1.2.jar".
4.2. Installing Apache
Jakarta Commons FileUpload and Commons IO into a Servlet/JSP
Container Like Tomcat
Next,
we need to install the Apache Jakarta Commons FileUpload library and
the Apache Jakarta Commons IO library into a Servlet/JSP container
such as Apache Tomcat. To do this, copy the JAR files
"commons-fileupload-1.1.1.jar" and "commons-io-1.2.jar"
to the /WEB-INF/lib/ directory in the document root of your web
application.
Note
that JAR libraries stored in /WEB-INF/lib/ will be available to the
containing web application only. If you want to share the libraries
among all web applications installed in Tomcat (suppose you are using
Tomcat 5 or Tomcat 4), the JAR files should be copied to the
$CATALINA_HOME/shared/lib/ directory, where $CATALINA_HOME
is the root of your Tomcat installation.
4.3. Checking If an HTTP
Request is Encoded in Multipart Format
Now
that you have installed the Apache Jakarta Commons FileUpload
library, you can start writing the code. First, we have to make sure
the HTTP request is encoded in multipart format. This can be done
using the static method isMultipartContent() of the
ServletFileUpload class of the org.apache.commons.fileupload.servlet package:
if
(ServletFileUpload.isMultipartContent(request)){ // Parse the
HTTP request... }
In
the above Java code snippet, request
is a javax.servlet.http.HttpServletRequest
object that encapsulates the HTTP request. It should be very
familiar to you if you know Java Servlet or JSP.
4.4. Parsing Form Data
with Java Servlet / JSP
Second,
we will parse the form data contained in the HTTP request. Parsing
the form data is very straightforward with the Apache Jakarta Commons
FileUpload library:
ServletFileUpload
servletFileUpload = new ServletFileUpload(new
DiskFileItemFactory()); List fileItemsList =
servletFileUpload.parseRequest(request);
(In the above Java code snippet,
DiskFileItemFactory is a class contained in the org.apache.commons.fileupload.disk
package and List is an interface contained in the java.util package.)
If
everything works fine, fileItemsList
will contain a list of file items that are instances of FileItem of
the org.apache.commons.fileupload package. A file item
may contain an uploaded
file or a simple name-value pair of a form field. (More details about
FileItem will be provided later.)
By
default, the ServletFileUpload
instance created by the above Java code uses the following values
when parsing the HTTP request:
Size
threshold = 10,240 bytes. If the size of a file item is
smaller than the size threshold, it will be stored in the memory.
Otherwise it will be stored in a temporary file on disk.
Maximum
HTTP request body size = -1, which means the server will accept HTTP
request bodies of any size.
Repository
= System default temp directory, whose value can be found by the
Java code System.getProperty("java.io.tmpdir").
Temporary files will be stored there.
If
you do not like the default settings, you can change them using the
methods setSizeThreshold()
and setRespository()
of the DiskFileItemFactory
class and the setSizeMax()
method of the ServletFileUpload
class, like this:
DiskFileItemFactory
diskFileItemFactory = new
DiskFileItemFactory(); diskFileItemFactory.setSizeThreshold(40960);
/* the unit is bytes */
File repositoryPath = new
File("/temp"); diskFileItemFactory.setRepository(repositoryPath);
ServletFileUpload
servletFileUpload = new
ServletFileUpload(diskFileItemFactory); servletFileUpload.setSizeMax(81920);
/* the unit is bytes */
(In the above Java code snippet, File is
a class of the java.io package.)
If
the size of the HTTP request body exceeds the maximum you set, the
SizeLimitExceededException
exception (fully qualified name: org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException)
will be thrown when you call the parseRequest()
method:
try
{ List fileItemsList =
servletFileUpload.parseRequest(request); /* Process file
items... */ } catch (SizeLimitExceededException ex) { /*
The size of the HTTP request body exceeds the limit */ }
4.5. Iterating through
File Items
Third,
we will iterate through the file items and process each of them. The
isFormField() method of the
FileItem interface is used
to determine whether a file item contains a simple name-value pair of
a form field or an uploaded file:
Iterator
it = fileItemsList.iterator(); while (it.hasNext()){ FileItem
fileItem = (FileItem)it.next(); if
(fileItem.isFormField()){ /* The file item contains a
simple name-value pair of a form field */ } else{ /*
The file item contains an uploaded file */ } }
(In the above Java code snippet, Iterator
is an interface in the java.util package and FileItem is an
interface in the org.apache.commons.fileupload package.)
Feedback Form (ExpandCollapse)
|
|