Академический Документы
Профессиональный Документы
Культура Документы
FileUpload can be used in a number of different ways, depending upon the requirements of your application.
In the simplest case, you will call a single method to parse the servlet request, and then process the list of
items as they apply to your application. At the other end of the scale, you might decide to customize
FileUpload to take full control of the way in which individual items are stored; for example, you might decide
to stream the content into a database.
Here, we will describe the basic principles of FileUpload, and illustrate some of the simpler - and most
common - usage patterns. Customization of FileUpload is described elsewhere .
FileUpload depends on Commons IO, so make sure you have the version mentioned on the dependencies page
in your classpath before continuing.
How it works
A file upload request comprises an ordered list of items that are encoded according to RFC 1867 , "Form-
based File Upload in HTML". FileUpload can parse such a request and provide your application with a list of
the individual uploaded items. Each such item implements the FileItem interface, regardless of its underlying
implementation.
This page describes the traditional API of the commons fileupload library. The traditional API is a convenient
approach. However, for ultimate performance, you might prefer the faster Streaming API .
Each file item has a number of properties that might be of interest for your application. For example, every
item has a name and a content type, and can provide an InputStream to access its data. On the other hand,
you may need to process items differently, depending upon whether the item is a regular form field - that is,
the data came from an ordinary text box or similar HTML field - or an uploaded file. The FileItem interface
provides the methods to make such a determination, and to access the data in the most appropriate manner.
FileUpload creates new file items using a FileItemFactory. This is what gives FileUpload most of its
flexibility. The factory has ultimate control over how each item is created. The factory implementation that
currently ships with FileUpload stores the item's data in memory or on disk, depending on the size of the item
(i.e. bytes of data). However, this behavior can be customized to suit your application.
If you are building a portlet application, the following are the two distinctions you should make as you read
this document:
• Where you see references to the ServletFileUpload class, substitute the PortletFileUpload class.
• Where you see references to the HttpServletRequest class, substitute the ActionRequest class.
Now we are ready to parse the request into its constituent items.
The simplest case
• Uploaded items should be retained in memory as long as they are reasonably small.
• Larger items should be written to a temporary file on disk.
• Very large upload requests should not be permitted.
• The built-in defaults for the maximum size of an item to be retained in memory, the maximum
permitted size of an upload request, and the location of temporary files are acceptable.
The result of the parse is a List of file items, each of which implements the FileItem interface. Processing
these items is discussed below.
If your usage scenario is close to the simplest case, described above, but you need a little more control, you
can easily customize the behavior of the upload handler or the file item factory or both. The following
example shows several configuration options:
Of course, each of the configuration methods is independent of the others, but if you want to configure the
factory all at once, you can do that with an alternative constructor, like this:
Should you need further control over the parsing of the request, such as storing the items elsewhere - for
example, in a database - you will need to look into customizing FileUpload.
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
For a regular form field, you will most likely be interested only in the name of the item, and its String value.
As you might expect, accessing these is very simple.
For a file upload, there are several different things you might want to know before you process the content.
Here is an example of some of the methods you might be interested in.
With uploaded files, you generally will not want to access them via memory, unless they are small, or unless
you have no other alternative. Rather, you will want to process the content as a stream, or write the entire file
to its ultimate location. FileUpload provides simple means of accomplishing both of these.
Note that, in the default implementation of FileUpload, write() will attempt to rename the file to the
specified destination, if the data is already in a temporary file. Actually copying the data is only done if the the
rename fails, for some reason, or if the data was in memory.
If you do need to access the uploaded data in memory, you need simply call the get() method to obtain the
data as an array of bytes.
Resource cleanup
This section applies only, if you are using the DiskFileItem . In other words, it applies, if your uploaded files
are written to temporary files before processing them.
Such temporary files are deleted automatically, if they are no longer used (more precisely, if the
corresponding instance of java.io.File is garbage collected. This is done silently by the
org.apache.commons.io.FileCleaner class, which starts a reaper thread.
This reaper thread should be stopped, if it is no longer needed. In a servlet environment, this is done by using
a special servlet context listener, called FileCleanerCleanup . To do so, add a section like the following to
your web.xml:
<web-app>
...
<listener>
<listener-class>
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
...
</web-app>
Creating a DiskFileItemFactory
To disable tracking of temporary files, you may set the FileCleaningTracker to null. Consequently, created
files will no longer be tracked. In particular, they will no longer be deleted automatically.
The default implementation of FileUpload will cause uploaded items above a certain size threshold to be
written to disk. As soon as such a file is closed, any virus scanner on the system will wake up and inspect it,
and potentially quarantine the file - that is, move it to a special location where it will not cause problems. This,
of course, will be a surprise to the application developer, since the uploaded file item will no longer be
available for processing. On the other hand, uploaded items below that same threshold will be held in
memory, and therefore will not be seen by virus scanners. This allows for the possibility of a virus being
retained in some form (although if it is ever written to disk, the virus scanner would locate and inspect it).
One commonly used solution is to set aside one directory on the system into which all uploaded files will be
placed, and to configure the virus scanner to ignore that directory. This ensures that files will not be ripped out
from under the application, but then leaves responsibility for virus scanning up to the application developer.
Scanning the uploaded files for viruses can then be performed by an external process, which might move
clean or cleaned files to an "approved" location, or by integrating a virus scanner within the application itself.
The details of configuring an external process or integrating virus scanning into an application are outside the
scope of this document.
Watching progress
If you expect really large file uploads, then it would be nice to report to your users, how much is already
received. Even HTML pages allow to implement a progress bar by returning a multipart/replace response, or
something like that.
Do yourself a favour and implement your first progress listener just like the above, because it shows you a
pitfall: The progress listener is called quite frequently. Depending on the servlet engine and other environment
factory, it may be called for any network packet! In other words, your progress listener may become a
performance problem! A typical solution might be, to reduce the progress listeners activity. For example, you
might emit a message only, if the number of megabytes has changed:
What's next
Hopefully this page has provided you with a good idea of how to use FileUpload in your own applications.
For more detail on the methods introduced here, as well as other available methods, you should refer to the
JavaDocs .
The usage described here should satisfy a large majority of file upload needs. However, should you have more
complex requirements, FileUpload should still be able to help you, with it's flexible customization
capabilities.