How many times have you asked yourself or been curious about how the developers at Hotmail or Yahoo Mail process the attachments to your email? Rest assured that you are not the only one. Too often Java Internet developers only concentrate on processing strings from an HTML form, and when asked by the boss if they can do file upload, they have to do some research before they can come back with an answer. File upload is too rarely discussed by even respectable Java literature.
And, with the growth of the Internet, file upload has now also
played significant roles beyond email applications. Other
Internet/intranet applications such as Web-based document management
systems and the likes of "Secure File Transfer via HTTP" require
uploading files to the server extensively. This article discusses all
you need to know about file upload. But first things first. Before you
jump too excitedly into coding, you need to understand the underlying
theory: the HTTP request. Knowledge of the HTTP request is critical
because when you process an uploaded file, you work with raw data not
obtainable from an HttpServletRequest object's methods
such as getParameter, getParameterNames, or
getParameterValues.
Each HTTP request from the Web browser or other Web client applications consists of three parts:
These three parts are explained in the following sections.
The first subpart of the first part, the HTTP request method,
indicates the method used in the HTTP request. In HTTP 1.0, it could
be one of the following three: get, head, or
post. In HTTP 1.1, in addition to the three methods,
there are four more methods: delete, put,
trace, and options. Among the seven, the two
methods that are most frequently used are get and
post. get is the default method. You use it,
for example, when you type a URL such as
http://www.onjava.com in the Location or Address box of your
browser to request a page. The post method is common
too. You normally use this as the value of the
<form> tag's method attribute. When
uploading a file, you must use the post method.
The second part of the first part, the URI, specifies an Internet
resource. A URI is normally interpreted as being relative to the Web
server's root directory. Thus, it starts with a forward slash
(/) that is of the following format.
/virtualRoot/pageName
For example, in a typical JavaServer Pages application the URI could be the following.
/eshop/login.jsp
More information about URI can be found here.
The third component of the first part is the protocol and the protocol version understood by the requester (the browser). The protocol must be HTTP and the version could be 1.0 or 1.1. Most Web servers understand both versions 1.0 and 1.1 of HTTP. Therefore, this kind of Web server can serve HTTP requests in both versions as well. If you are still using an old HTTP 1.0 Web server, you could be in trouble if your users use modern browsers that send requests using HTTP 1.1 protocol.
Combining the three sub-parts of the first component of an HTTP request, the first component would look like the following.
POST /virtualRoot/pageName HTTP/version
For instance:
POST /eshop/login.jsp HTTP/1.1
The second component of an HTTP request consists of a number of HTTP headers. There are four types of HTTP headers: general, entity, request, and response. These headers are summarized in Tables 1, 2 and 3. The response headers are HTTP Response specific, thus not relevant to be discussed here.
| Table 1: HTTP General Headers | |
| Header | Description |
| Pragma | The Pragma general header is used to include implementation specific directives that may apply to any recipient along the request/response chain. This is to say that pragmas notify the servers that are used to send this request to behave in a certain way. The Pragma header may contain multiple values. For example, the following line of code inform all proxy servers that relay this request not to use a cached version of the object but to download the object from the specified location:
|
| Date | The Date general header represents the date and time at which the message was originated. |
| Table 2: HTTP Entity Headers. | |
| Header | Description |
| Allow | This header lists the
set of method supported by the resource identified by the requested
URL. The purpose of this field is strictly to inform the recipient of
valid methods associated with the resource. The Allow header is not
permitted in a request using the
|
| Content-Encoding | This header is used to describe the type of encoding used on the entity. When present, its value indicates the decoding mechanism that must be applied to obtain the media type referenced by the Content-Type header. For example,
|
| Content-Length | This header
indicates the size of the entity-body, in decimal number of octets,
sent to the recipient or, in the case of the |
| Content-Type | The
Content-Type header indicates the media type of the entity-body sent
to the recipient or, in the case of the
|
| Expires | The Expires header gives the date and time after which the entity should be considered invalid. This allows information providers to suggest the volatility of the resource or a date after which the information may no longer be accurate. Applications must not cache this entity beyond the date given. The presence of an Expires header does not imply that the original resource will change or cease to exist at, before, or after that time. However, information providers should include an Expires header with that date. For example,
|
| Last-Modified | The Last-Modified header indicates the date and time at which the sender believes the resource was last modified. The exact semantics of this field are defined in terms of how the recipient should interpret it. If the recipient has a copy of this resource that is older than the date given by the Last-Modified field, that copy should be considered stale For example,
|
| Table 3: HTTP Request Headers | |
| Header | Description |
| From | The From header specifies who is taking responsibility for the request. This field contains the email address of the user submitting the request. For example,
|
| Accept | This header contains a semicolon-separated list of MIME representation schemes that are accepted by the client. The server uses this information to determine which data types are safe to send to the client in the HTTP response. Although the Accept field can contain multiple values, the Accept line itself can also be used more than once to specify additional accept types (this has the same effect as specifying multiple accept types on a singe line). If the Accept filed is not used in the request header, the default accepts types of text/plain and text/html are assumed. For example,
|
| Accept-Encoding | This header is very similar to the accept header in syntax. However, it specifies the content-encoding schemes that are acceptable in the response. For instance,
|
| Accept-Language | This header is also similar to the Accept header. It specifies the preferred response language. The following example specifies English as the accepted language:
|
| User-Agent | The User-Agent, if present, specifies the name of the client browser. The first word should be the name of the software followed by a slash and an optional version number. Any other product names that are part of the complete software package may also be included. Each name/version pair should be separated by white space. This field is used mostly for statistical purposes. It allows servers to track software usage and protocol violation. For example,
|
| Referer | This header specifies the URI that contained the URI in the request header. In HTML, it would be the address of the page that contained the link to the requested object. Like the User-Agent header, this header is not required but is mostly for the server's statistical and tracking purpose. For example,
|
| Authorization | The Authorization header contains authorization information. The first word contained in this header specifies the type of authorization system to use. Then, separated by white space, it should be followed by the authorization information such as a user name, password, and so forth. For example, |
| If-Modified-Since | This header is used with the GET method to make it conditional. Basically, if the object hasn't changed since the date and time specified by this header, the object is not sent. A local cached copy of the object is used instead. For example, If-Modified-Since: Thu, 10 Aug 2000 12:12:29 GMT |
|
The entity body is the content of the HTTP request itself. It is best to illustrate this with an example. An example of an HTTP header is given below.
Accept: application/vnd.ms-excel, application/msword, */*
Accept-Language: en-au
Connection: Keep-Alive
Host: localhost
Referer: http://localhost/examples/jsp/num/demo.jsp
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
LastName=truman&FirstName=daniel
A lot is revealed in the HTTP header above. The first line tells us
that the browser that sends this request can accept a number of file
formats, including Microsoft Excel and Microsoft Word. It is followed
by the language used (in this case, Australian English), the type of
connection (keep-alive), and the name of the host (localhost). It also
tells the server that the request is sent from the
demo.jsp which is located in
http://localhost/examples/jsp/num/ directory. Then in the
User-Agent entry, the Request tells that the user is using a Microsoft
Internet Explorer version 4.01, which is compatible with Netscape
4.0. The user operation system is also recorded to be Windows 98. The
meaning of the information to follow can be retrieved from the
previous tables.
Following the header is two pairs of carriage-return line-feed characters. The length of this separator is 4 bytes since each carriage-return line-feed character pair consists of the ASCII characters number 13 and 10. From the HTTP header above we can see that the body consists of the following code:
LastName=truman&FirstName=daniel
This is clearly from a form with two input boxes: one called
LastName with the value truman and the other
named FirstName with the value daniel.
Note that the length of
LastName=truman&FirstName=daniel is 32.
Now that you have finished dissecting an HTTP request, you are ready to take this information to the coding stage. To program a complete file upload application, you need to know both the server side and the client side. First we will learn how to program the HTML on the client side, and then we will study the Java code for the server side.
Prior to the RFC 1867 standard, there were eight possible values
for the type attribute of an input element:
checkbox, hidden, image,
password, radio, reset,
submit, and text. While these form elements
have proven useful in a wide variety of applications in which input
from the user needs to be transferred to the server, none of these is
useful for sending a file, either text or binary. Next, it was
proposed that the Type attribute of an Input element has another
possible value: file. In addition, it defines a new MIME
media type, multipart/form-data, and specifies the behavior of HTML
user agents when interpreting a form with
enctype="multipart/form-data" or <input
type="file" /> tags.
The author of an HTML form who wants to request one or more files from a user might write:
<form action="Jsp1.jsp" enctype="multipart/form-data" method="post">
File to Upload: <input name="filename" type="file" />
<br />
<input type="submit" value="Upload" />
</form>
When an input tag of type file is
encountered, the browser might show a display of previously selected
file names and a "Browse" button or selection method. Selecting the
"Browse" button would cause the browser to enter into a file selection
mode appropriate for the platform. Window-based browsers might pop up
a file selection window, for example. In such a file selection dialog,
the user would have the option of replacing a current selection,
adding a new file selection, etc.
Internet programming in Java always involves the use of Servlets or
JSP pages, depending on the architecture you choose to implement. This
means that you will use one of the classes or interfaces in the
javax.servlet package or the
javax.servlet.http package. The most important interface
is the Servlet interface in the javax.servlet package
that must be implemented by all servlets. However, I will not present
an introduction to Servlets in this article and can only refer you to
Sun's Web site if you need more
details about this API. What is of importance here is the HTTP request
and how to process it. When working with the HTTP request, you will
work with either the javax.servlet.ServletRequest
interface or javax.servlet.http.HttpServletRequest. The
ServletRequest interface is a generic interface that is
extended by HttpServletRequest to provide request
information for HTTP Servlets.
The HttpServletRequest interface has the following
signature.
public interface HttpServletRequest extends ServletRequest
The Servlet container creates an HttpServletRequest
object and passes it as an argument to the Servlet's service methods
(doGet, doPost, etc). For a File Upload
Bean, you can then pass this HttpServletRequest object to
the Bean for further processing, like the one in this article.
Some important methods of HttpServletRequest are given
in the following list.
public long getDateHeader(java.lang.String
name)
Returns the value of the specified request header as a
longvalue that represents aDateobject. Use this method with headers that contain dates, such asIf-Modified-Since.The date is returned as the number of milliseconds since January 1, 1970 GMT. The header name is case insensitive.
If the request did not have a header of the specified name, this method returns
-1. If the header can't be converted to a date, the method throws anIllegalArgumentException.
public java.lang.String getHeader(java.lang.String
name)
Returns the value of the specified request header as a
String. If the request did not include a header of the specified name, this method returnsnull. The header name is case insensitive. You can use this method with any request header.
public java.util.Enumeration
getHeaderNames()
Returns an enumeration of all the header names this request contains. If the request has no headers, this method returns an empty enumeration.
Some Servlet containers do not allow do not allow Servlets to access headers using this method, in which case this method returns
null
public java.util.Enumeration
getHeaders(java.lang.String name)
Returns all the values of the specified request header as an
EnumerationofStringobjects.Some headers such as
Accept-Languagecan be sent by clients as several headers each with a different value rather than sending the header as a comma separated list.If the request did not include any headers of the specified name, this method returns an empty
Enumeration. The header name is case insensitive. You can use this method with any request header.
public java.lang.String getMethod()
Returns the name of the HTTP method with which this request was made, for example,
get,post, orput. This is the same as the value of the CGI variableREQUEST_METHOD.
public java.lang.String
getPathInfo()
Returns any extra path information associated with the URL the client sent when it made this request. The extra path information follows the Servlet path but precedes the query string. This method returns
nullif there was no extra path information.This is the same as the value of the CGI variable
PATH_INFO.
public java.lang.String
getPathTranslated()
Returns any extra path information after the Servlet name but before the query string and translates it to a real path. This is the same as the value of the CGI variable
PATH_TRANSLATED.If the URL does not have any extra path information, this method returns
null.
public java.lang.String
getQueryString()
Returns the query string that is contained in the request URL after the path. This method returns null if the URL does not have a query string. This is the same as the value of the CGI variable
QUERY_STRING.
public java.lang.String
getRemoteUser()
Returns the login of the user making this request, if the user has been authenticated, or
nullif the user has not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication. This is the same as the value of the CGI variableREMOTE_USER.
public java.lang.String
getRequestedSessionId()
Returns the session ID specified by the client. This may not be the same as the ID of the actual session in use. For example, if the request specified an old (
expired) session ID and the server has started a new session, this method gets a new session with a new ID. If the request did not specify a session ID, this method returnsnull.
public java.lang.String
getRequestURI()
Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.
public java.lang.String
getServletPath()
Returns the part of this request's URL that calls the Servlet. This includes either the Servlet name or a path to the Servlet, but does not include any extra path information or a query string. This is the same as the value of the CGI variable
SCRIPT_NAME.
public HttpSession getSession(boolean
create)
Returns the current
HttpSessionassociated with this request or, if there is no current session andcreateis true, returns a new session.If
createis false and the request has no validHttpSession, this method returns null.To make sure the session is properly maintained, you must call this method before the response is committed.
public HttpSession getSession()
Returns the current session associated with this request or, if the request does not have a session, creates one.
To illustrate how you can process a file upload, you should
familiarize yourself with the HTTP request of an uploaded file. The
following small application demonstrates how to upload a file and
writes the HTTP request into a file. Viewing the file with a text
editor will reveal the format of the request, which in turn enables
you to extract the filename, the file content, and other useful
information that are mixed together. This small application is meant
as a preparation before we discuss the real File Upload Bean and
consists of an HTML file called main.html, a JSP file
called Jsp1.jsp, and a JavaBean called
SimpleBean.
The main.html file is the one that the client can use
to select a file to upload to the server and is given as follows.
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form action="jsp1.jsp" enctype="MULTIPART/FORM-DATA" method=post>
Author: <input type="text" name="author" />
<br />
Company: <input type="text" name="company" />
<br />
Select file to upload <input type="file" name="filename" />
<br />
<input type="submit" value="Upload" />
</form>
</body>
</html>
You can see that the enctype attribute is used in the
<form> tag and its value is
"MULTIPART/FORM-DATA". There are four input elements
including the submit button. The first two are normal
text elements called Author and Company. The third one is
an element of type file, the input element that is used
to select a file.
The action attribute of the form has the value of
Jsp1.jsp, meaning that the request (and also the file
uploaded) is sent to the Jsp1.jsp file.
The Jsp1.jsp simply calls a Bean called
SimpleBean.
<jsp:useBean id="TheBean" scope="page" class="SimpleBean " />
<%
TheBean.doUpload(request);
%>
And here is the code for the SimpleBean Bean.
import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletInputStream;
public class FileUploadBean {
public void doUpload(HttpServletRequest request) throws
IOException {
PrintWriter pw = new PrintWriter(
new BufferedWriter(new FileWriter("Demo.out")));
ServletInputStream in = request.getInputStream();
int i = in.read();
while (i != -1) {
pw.print((char) i);
i = in.read();
}
pw.close();
}
}
It will write everything on the HttpServletRequest
object to a file named Demo.out.
The user interface is given by the main.html file and
is shown in Figure 1. For this example, we enter some input values for
the Author and Company input elements and select a file called
abisco.html with the following content. I select an HTML
file to upload because I would like to show the content of the file in
the format. Since an HTML file is more or less a text file, the
content will be easy to display.
|
The content of the abisco.html file is as follows.
<html>
<head>
<title>Abisco</title>
</head>
</html>
|
When you click the Upload button (see Figure 1 again), the form
will be sent. This includes the file called abisco.html. This form is
submitted to the Jsp1.jsp file. This JSP file itself does
not return any response to the browser. However, it creates a file
called Demo.out.
Open the Demo.out file, and you will see the
following.
-----------------------------7d15340138
Content-Disposition: form-data; name="Author"
A. Christie
-----------------------------7d15340138
Content-Disposition: form-data; name="Company"
Abisco
-----------------------------7d15340138
Content-Disposition: form-data; name="Filename"; filename="C:\123data\abisco.html"
Content-Type: text/html
<html>
<head>
<title>Abisco</title>
</head>
</html>
-----------------------------7d15340138--
In brief, the entity body of the HTTP request contains all the form input, including the uploaded file. Those input values are separated from each other by a delimiter. Sometimes called a boundary, this delimiter consists of a few dozen dash characters followed by a random number. In the example above, the delimiter is the following line.
-----------------------------7d15340138
The last delimiter ends the entity body with two more dashes.
For an input value that comes from a non-file element, the delimiter is follows by the following line.
Content-Disposition: form-data; name=inputName
where inputName is the name of the form element.
For example:
Content-Disposition: form-data; name="Author"
Two sequences of carriage return linefeed characters and the element value follow the line.
For the file, two lines follow the delimiter. The first contains
the name of the FILE input element and the complete path
of the file in the user's computer. From the HTTP request above, this
line is as follows.
Content-Disposition: form-data; name="Filename"; filename="C:\123data\abisco.html"
It states that the FILE input element is called Filename and the
file path is C:\123data\abisco.html. Note that Windows
browsers include the file path, but Unix/Linux and Mac browsers only
send the filename.
The second line contains the content type of the file. Therefore, its value depends on the file being uploaded. For this example, the value is text/html.
Content-Type: text/html
Like the non-File input element, the content starts after two sequences of carriage return linefeed characters.
That's all you need to know to write a File Upload Bean.
Some file upload code is written as part of a bigger application. Often the piece of code that does the extraction of the uploaded file is integrated with the other pieces as a whole, making it unusable for other applications. The solution here gives you the file upload function in a Bean, which we all know is a component in the Java platform. As such, this Bean is portable and can be used in any application that requires file upload.
I call this Bean Brainy FileUploadBean. The complete code is given in Listing 1. This section gives you the detailed descriptions of what the code does, so that you can extend the functionality if you so desire.
The first line of code is the package information. When I wrote the Bean, it was part of the package called com.brainysoftware.web. You probably don't want to use the same name for the package; therefore you should change the first line of the code.
package com.brainysoftware.web;
Alternatively, you can remove this line entirely if you don't want the class to be a member of any package.
Next are the import statements that tell you what classes or
interfaces are used in the Bean. Of special interest are the
HttpServletRequest interface from the
javax.servlet.http package and the abstract class
ServletInputStream from the javax.servlet
package. This class is a subclass of
java.io.InputStream.
Also imported are Dictionary and Hashtable from the
java.util package and PrintWriter, BufferedWriter,
FileWriter, and IOException from the java.io package.
Then comes the class, FileUploadBean. The class has 5 private fields, 6 public methods and 2 private methods.
The five fields of the FileUploadBean class are all private. They are as follows.
private String savePathprivate String filepathprivate String filenameprivate String contentTypeprivate Dictionary fieldsThe first four public methods are used to return the FileUploadBean object's private fields. They are getFilepath, getFilename, getContentType and getFieldValue.
public String getFilepath()public String getFilename()public String getContentType()public String getFieldValue(String fieldName)public void setSavePath(String savePath)You pass the HttpServletRequest object created by the Servlet/JSP container to the doUpload method. This object represents the HTTP request that you need to process to extract the HTML form's element names-values and the uploaded file. The method starts by obtaining the ServletInputStream object using the getInputStream method of the HttpServletRequest object.
As explained before, each form element is separated by the boundary and a sequence of carriage return line feed characters. Therefore, you can read the content of the HttpServletRequest object line by line. The following line of code defines a byte array called line.
byte[] line = new byte[128];
You then use the readLine method of ServletInputStream to read the first line of the HttpServletRequest object's content.
int i = in.readLine(line, 0, 128);
The first line should be the boundary, and its length, if no error has occurred, should be much longer than 3. Therefore, a length of less than three can be assumed erroneous and the doUpload method should exit.
if (i < 3)
return;
The boundary and the length of the boundary are important values, as you will see later. The boundary is terminated by a sequence of carriage return linefeed characters. Therefore the actual length is two less than the number of bytes returned by the readLine method.
int boundaryLength = i - 2;
The boundary is retrieved from the byte array line by discarding the last two carriage return linefeed characters.
String boundary = new String(line, 0, boundaryLength);
The field fields is then instantiated with a Hashtable object. This Hashtable object is used to store the HTML form element name/value pairs.
fields = new Hashtable();
Having the boundary you can then start extracting the form element value by reading the HttpServletRequest object's content line by line using the while loop, until it reaches the end of it when the readLine method returns -1. All HTML form elements start with a boundary followed by the content-disposition line that starts with the following characters.
Content-Disposition: form-data; name=
There are two types of form elements: file and non-file (normal form elements such as TEXT or HIDDEN elements). The difference between the two is based on the file element, which contains the following string.
filename="filename"
Therefore, you can use this information to distinguish the file from the non-file input elements using the following two if statements.
if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
if (newLine.indexOf("filename=\"") != -1) {
// a file form element, code to extract the file here
. . .
}
else {
//this is a field, code to extract fields here
. . .
}
}
Now, let's a look at the code to extract the file content first. Afterwards, we have a look at the code to extract non-file form elements.
The filepath is contained in the content-disposition. To retrieve
the file path and the filename, the doUpload method calls
the setFilename private method. This method will be
discussed in the next section but it is sufficient to say that
setFilename extracts the file path and the filename information and
assign them to the filepath and filename fields.
After the setFilename method call, filename should not
be null. Otherwise, an error has occurred and the
doUpload method returns entirely.
if (filename==null)
return;
The next line after the content-disposition line is the content
type line. So call the readLine method again and call the
setContentType private method. This method is similar to
setFilename. It retrieves the content type of the
uploaded file from the raw bytes and assign it contentType.
The next line after the line that contains the file content type is a blank line. Therefore, call the readLine method again.
i = in.readLine(line, 0, 128);
Then, begins the actual file content. We should be ready to write
the file to the disk, using a PrinterWriter object.
PrintWriter pw = new PrintWriter(new BufferedWriter(
new FileWriter(
( savePath==null? "" : savePath ) + filename
)));
Where the file should be saved to depends on whether the
savePath field has been set. If the savePath
was not set, its value is null, and the file should be saved in the
default directory. If the savePath field has been set,
its value will not be null so the uploaded file must be uploaded to
this directory.
We can then extract the file content by using a while loop that reads one line at a time and writes it to disk using the write method of the PrintWriter. However, we know that the last line of the file includes two carriage return line feed characters. Therefore, the bytes saved to the disk must not include these two characters. So if the line read is not the last line of the file, write all the bytes read to the disk. If it is, write all the bytes read minus the last two characters.
However, we do not know the size of the file. What we know is that the next line after the file content is another boundary. Or, if the file is the last HTML form element, the next line is the boundary plus two dash characters. Therefore, by checking whether or not the next line is a boundary we will know how to exit from the while loop. This is the reason why I said the boundary value was important. We need the boundary value for this.
We could read the next line and use the startsWith
method to check if the next line is a boundary. However, string
manipulation is expensive. To avoid string manipulation, we compare
the length of the byte array read by readLine. The latter
should be equal to boundaryLength + 2. Or, if it is the last line in
the HttpServletRequest object, it should be equal to
boundaryLength + 4 because of the last two dash characters. Because a
line could also be as long as a boundary without being a boundary, we
compare it with the boundary when the length matches. Now you know why
the boundaryLength value is also important.
|
The whole thing is illustrated by the following lines of code.
while (i != -1 && !newLine.startsWith(boundary)) {
i = in.readLine(line, 0, 128);
if ((i==boundaryLength+2 || i==boundaryLength+4) // + 4 is eof
&& (new String(line, 0, i).startsWith(boundary)))
pw.print(newLine.substring(0, newLine.length()-2));
else
pw.print(newLine);
newLine = new String(line, 0, i);
}
After the file content is saved to the disk, close the PrintWriter.
pw.close();
The non-file form elements can be retrieved similarly. Instead of writing the values to the disk, however, the name-value pairs are put into the Dictionary object.
fields.put(fieldName, fieldValue.toString());
private void setFilename(String
s)Once you compile the Bean, you can use it from your Servlet or JSP page. Chances are you are using the Bean with a Servlet/JSP container such as Tomcat. The easiest way to deploy the Bean is to compress the class file into a jar file and chuck it to the lib directory of Tomcat. You need to restart Tomcat for the jar file to be loaded.
The following are an HTML file and a JSP file that illustrate the use of the Bean. The HTML file contains a form with a few elements.
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form action=jsp1.jsp enctype="MULTIPART/FORM-DATA" method=post>
Author: <input type=text name=author>
<br>
Company: <input type=text name=company>
<br>
Comment: <textarea name=comment></textarea>
<br>
Select file to upload <input type=file name=filename>
<br>
Description: <input type=text name=description>
<br>
<input type=submit value="Upload">
</form>
</body>
</html>
When the user submits the form, the HTTP request will be handed to
Jsp1.jsp, which uses the FileUpload Bean to process the
request. The code of the Jsp1.jsp is given below.
<jsp:useBean id="TheBean" scope="page"
class="com.brainysoftware.web.FileUploadBean" />
<%
TheBean.doUpload(request);
out.println("Filename:" + TheBean.getFilename());
out.println("<BR>Content Type:" + TheBean.getContentType());
out.println("<BR>Author:" + TheBean.getFieldValue("Author"));
out.println("<BR>Company:" + TheBean.getFieldValue("Company"));
out.println("<BR>Comment:" + TheBean.getFieldValue("Comment"));
%>
File upload is not an easy topic and code to process it is not readily available. This article has presented the theory as well as the code for a File Upload Bean. The compiled version of the Bean is available for download from my Web site.
Budi Kurniawan is a senior J2EE architect and author.
Return to ONJava.com.
Copyright © 2007 O'Reilly Media, Inc.