Answers to the most frequently asked
questions
Below you'll find questions and answers
to the most frequently asked questions about the com.oreilly.servlet
library, especially the file upload components.
If you have other questions, write to cos-inquiry at servlets dot com.
What is the com.oreilly.servlet package?
The com.oreilly.servlet package is a "must
have" class library for servlet developers. There are classes
to help servlets handle file uploads, generate multipart responses
(server push), parse parameters, negotiate locales for internationalization,
return files, manage socket connections, and act as RMI servers,
as well as a class to help applets communicate with servlets. Since
the first release, there are also new classes to help servlets send
email messages, cache responses, and auto-detect servlet API support.
The latest version is available online (with javadoc documentation)
for download from http://www.servlets.com.
How do I install the com.oreilly.servlet package?
Unzip the com.oreilly.servlets distribution file
using a unzip utility like WinZip or jar. Inside you'll find a file
cos.jar. Place this where your server will find it, such as the
WEB-INF/lib directory for your web application. For server-wide
availability you can also place it into the CLASSPATH used by your
server. That's it!
For more information on the WEB-INF directory see
"Java Servlet Programming, 2nd Edition" and for more information
on CLASSPATH entries see any introductory Java book.
What's the difference between MultipartRequest
and MultipartParser?
MultipartRequest is an API for easyhandling
of multipart/form-data requests (commonly known as file uploads).
MultipartParser is an API for experts who want more control in handling
these requests. MultipartRequest handles the entire request and
then exposes the results while MultipartParser lets you walk the
request piece-by-piece and deal with each piece as it comes. MultipartRequest
is actually written as a thin facade on MultipartParser.
OK, so what's MultipartWrapper?
MultipartWrapper takes advantage of the filtering
capability introduced in Servlet API 2.3 to make handling file uploads
practically automatic. It can automatically wrap any request to
invisibly handle multipart/form-data requests. For more information,
see my filters
article at JavaWorld.
Why doesn't MultipartRequest implement the HttpServletRequest
interface?
It's an issue of forward compatibility. If MultipartRequest
had implemented HttpServletRequest back when
servlets were at API 2.0, then when API 2.1 came out and introduced
new methods into the request interface, all deployments of MultipartRequest
would have failed because MultipartRequest would no longer fully
implement the new HttpServletRequest. The same would have happened
with API 2.1 and 2.2. Now happily with API 2.3 there's an HttpServletRequestWrapper
class which protects against forward compatibility concerns, and
so MultipartWrapper does fully implement the HttpServletRequest
interface.
Why when using com.oreilly.servlet.MultipartRequest
or MultipartParser do large uploads fail?
The classes themselves were specifically designed
to have no maximum upload size limit (unlike
most other file upload utilities), but for your server's protection
the constructor allows you to set a maximum POST size to accept.
Any upload larger than the limit is halted. The default maximum
is 1 Meg. For a discussion of the difficulties a server has in notifying
a client of the error, see the discussion in Java Servlet Programming,
2nd Edition, page 119.
How can I configure a maximum upload size for
a single file but have no limit for the entire post?
The protocol doesn't make this easy. The only information
given to the server up front is the size of the entire POST. After
that, each file comes piece by piece with only a separator between
them. If you want to have a maximum file size, your best bet is
probably to use MultipartParser to walk the request piece by piece
and when writing any file keep track of how much is written and
if it exceeds your maximum you can remove the file and (if you like)
halt the upload. If you want to continue the upload, you'll need
to continue reading until the file it done before you can receive
the next file however.
How can I select a directory for the uploaded
files based on some information sent in the upload request?
Again, the protocol doesn't make this easy. In
fact, there's no sure guarantee the browser will send the parameter
information before the files. The safest approach is to create a
temporary directory, upload the files into there, then after the
upload move the files and/or the directory into the proper location.
Another alternative is to use MultipartParser to walk the request,
notice the parameter, and save later files accordingly.
Why when using com.oreilly.servlet.MultipartRequest
or MultipartParser am I getting an IOException saying "Corrupt
form data: premature ending" or "Separation boundary was
not specified" or "unexpected end of part"?
This indicates there was a problem parsing the
POST request submitted by the client. There can be many causes for
the problem:
- The client hit the STOP button (not really a problem, but it
does cause a premature ending)
- A bug in the web form
- A bug in the servlet
- A bug in the web server
- A bug in the browser
- A bug in the com.oreilly.servlet library itself
History has shown the web server to be the most frequent cause
of problems probably because there are so many different servers
and few vendors appear to test their binary upload capability.
First, make sure your client isn't hitting the
STOP button. Then, check if your problem is already posted on the
"Servlet bugs you need to know
about" resource on this site. If it's not well known, then
you get to be among the first to learn about it! And you can share
your discovery with us here!
Second, see if the upload works using the provided
upload.html form and DemoRequestUploadServlet.java class. Some people
have found bugs in their form that caused problems. Testing this
combination will see if that's the case. One user, Duke Takle, found
this exception was caused by a redirect: I was experiencing the
same "premature ending" as Albert Smith. What I've found
is that the problem was isolated to I.E. 5.0. The application that
troubled me was doing a redirect after the construction of a MultipartRequest.
It looks like this construction went well except on I.E. 5.0 the
browser attempted to make the request again and by that time the
ServletInputStream was empty. I've modified the application to simply
write the needed response instead of redirecting. This problem was
observed and fixed as described in Tomcat 4.0 and Weblogic 6.1.
Other users have found bugs in their handling servlet where
they call request.getParameter() instead of multipartRequest.getParameter(),
and some servers falsely read the input stream when their getParameter()
is called causing an "unexpected end of part".
If it still fails, the best way to isolate the
problem is to treat it like a hardware problem and swap out components
until things work, then use that knowledge to see what product has
the bug, or what interaction between products causes a bug. Try
swapping browsers first. You probably have multiple browsers available
to you so this should be easy. If one browser fails while others
work, it's likely an issue with that browser or how that browser
interacts with the server. Try uploading different files too, since
some files (especially binary files or files with long lines like
.doc files) could be triggering bugs. You can also test against
the Servlets.com upload demo at http://www.servlets.com/jservlet2/examples/ch04/index.html#ex04_21.
If your browser fails against that page, it's very likely the fault
of the browser because that page has been successful for many others.
If it looks like everything works on the demo site but not on your
server, it's very likely a server bug. Try installing a different
server to make sure, and if you isolate the problem report it to
your server vendor. Also please report it to us at bug-send at servlets dot com
so we can track it and help others.
How do I insert an uploaded file into a database?
The most obvious way, using filePart.writeTo()
into the database, doesn't work in a portable fashion because JDBC
expects to know the size up front, and the RFC 1867 format doesn't
give you the size; you have to read the entire file and then determine
the size by looking at what you received. There are a few ways that
do work.
First, if the file is small relative to the available
memory, you can load it into a memory buffer and move it into the
database:
filePart.writeTo(byteArrayOutputStream);
byte[] data = byteArrayOutputStream.toByteArray();
preparedStatement.setBytes(1, data); // db looks at data.length
Second, if the file is large relative to available
memory, you can copy the file to the filesystem (such as with MultipartRequest),
get a stream for reading from the file, and copy it into the database
from there.
Third, if your database has the right extensions,
you can stream directly into the database. For example, Oracle supports
this as shown in this LOBSample.
It requires casting to an Oracle-specific type. (If you have information
on other databases, please write in.)
I want to comply with your license, but I'd
like something simpler. Can I negotiate a different license?
Sure, contact cos-licensing@servlets.com.
Site-wide and company-wide licensing options are available, as well
as licenses for redistribution.
I want an applet client so I can upload a full
directory of files (or some such thing). Where can I find that?
Yes, see http://www.infomentum.com/appletfile/.
It's loaded with features like directory-at-a-time uploading. Tell
them Servlets.com sent you!