Before Servlet 3.0, processing file upload requires 3rd party libraries
such as Apache Commons
FileUpload. Servlet 3.0 (which requires Tomcat 7) builds in file
upload support.
File upload over HTTP is specified in "RFC 1867 Form-based File
Upload in HTML". Read "File Upload
using multipart/form-data POST Request".
Client-side HTML
Form: "FileUpload.html"
On the client-side, you provide an HTML <form> with an input
element <input type="file"> as follows:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8">
</head>
<body>
<h2>Upload File</h2>
<form
method="post" enctype="multipart/form-data"
action="upload">
Choose a file: <input
type="file" name="uploadedFile" /><br
/>
<input type="submit" />
</form>
</body>
</html>
Server-side
Servlet 3.0 introduces a new annotation
@MultipartConfig
with these attributes:
1.
location
: An absolute path to a directory in your
file system (NOT relative to your context root) to store files temporarily
while processing parts, when the file is bigger than fileSizeThreshold
. This
directory shall exist; otherwise, an IOException
will be thrown.
2.
fileSizeThreshold
: The file size in bytes after
which the file will be stored temporarily in the location
.
3.
maxFileSize
: The maximum file size in
bytes. If the size of the file is bigger than this, Tomcat throws an IllegalStateException
.
4.
maxRequestSize
: The maximum size in bytes
for the entire multipart/form-data
request (i.e., all the
parts).
For example,
@MultipartConfig(location="d:\\temp\\upload", fileSizeThreshold=1024*1024,
maxFileSize=5*1024*1024, maxRequestSize=2*5*1024*1024)
A new interface
javax.servlet.http.Part
is also introduced to represent a part of a form item that
were received within a multipart/form-data
POST request. The following methods are declared:
1.
getName()
: Get the name of this part.
2.
getSize()
: Get the size of this part.
3.
getInputStream()
: Get the content of this part
as an InputStream
.
4.
write(String filename)
: Write this part to file. The
filename is relative to the "location
" in @MultipartConfig
. The
container may simply rename the temporary file. Existing file will be
overridden.
5.
delete()
: Delete the underlying storage, including
the temporary file. Do not call delete()
after write()
.
6.
getContentType()
: Get the content type of this
part.
7.
getHeader(String name)
, getHeaders(String name)
, getHeaderNames()
: Get
the header.
The method
request.getParts()
(in javax.servlet.http.HttpServletRequest
) returns a collection of all parts. The request.getPart(String
name)
returns a Part
for given name attribute (if you have other input elements
besides file).
"FileUploadServlet30.java" with URL "/upload"
package com.programingsoeasy;
import java.io.*;
import
java.util.Collection;
import javax.servlet.*;
import
javax.servlet.annotation.*;
import
javax.servlet.http.*;
@WebServlet(
name = "upload",
urlPatterns = {"/upload"})
@MultipartConfig(
location="d:\\temp\\upload",
fileSizeThreshold=1024*1024,
maxFileSize=5*1024*1024,
maxRequestSize=2*5*1024*1024)
public class
FileUploadServlet30 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Collection<Part> parts =
request.getParts();
try {
out.write("<h2>Number of
parts : " + parts.size() + "</h2>");
for(Part part : parts) {
printPartInfo(part, out);
String filename =
getFileName(part);
if (filename != null) {
part.write(filename); //
relative to location in @MultipartConfig
}
}
} finally {
out.close();
}
}
@Override
protected void doGet(HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException {
getServletContext()
.getRequestDispatcher("/FileUpload.html")
.forward(request, response);
}
// Print the headers
for the given Part
private void printPartInfo(Part part,
PrintWriter writer) {
StringBuilder sb = new StringBuilder();
sb.append("<p>Name:
").append(part.getName()).append("<br>");
sb.append("ContentType:
").append(part.getContentType()).append("<br>");
sb.append("Size:
").append(part.getSize()).append("<br>");
for(String header :
part.getHeaderNames()) {
sb.append(header).append(":
").append(part.getHeader(header)).append("<br>");
}
sb.append("</p>");
writer.write(sb.toString());
}
// Gets the file name
from the "content-disposition" header
private String getFileName(Part part) {
for (String token :
part.getHeader("content-disposition").split(";")) {
if
(token.trim().startsWith("filename")) {
return token.substring(token.indexOf('=') +
1).trim()
.replace("\"",
"");
}
}
return null;
}
}
Total parts : 1
Name: uploadedFile
ContentType: text/plain
Size: 811
content-type:
text/plain
content-disposition:
form-data; name="uploadedFile"; filename="uploadedFile.txt"
1.
The client-side "FileUpload.html" has one
submission part, i.e., <input type="file">.
2.
The printPartInfo() prints the
headers of the given part. The output is as shown above.
3.
The part.write() method is
used to write the file under the location of the @MultipartConfig with the
filename extracted from the content-disposition header.
An Multi-part
HTML Form - "FileUploadMultipart.html"
The HTML form below has four input fields, which will be sent in four
parts, as shown in the output below.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8">
</head>
<body>
<h2>Upload File</h2>
<form method="post"
enctype="multipart/form-data" action="upload">
Who are you: <input
type="text" name="username" /><br />
Choose the file to upload: <input
type="file" name="file1" /><br />
Choose another file to upload: <input
type="file" name="file2" /><br />
Comments:<br />
<textarea
name="comment"></textarea><br />
<input type="submit"
value="SEND" />
</form>
</body>
</html>
Number of parts : 4
Name: username
ContentType: null
Size: 5
content-disposition:
form-data; name="username"
Name: file1
ContentType: text/plain
Size: 811
content-type:
text/plain
content-disposition:
form-data; name="file1"; filename="uploadedFile.txt"
Name: file2
ContentType: audio/mpeg
Size: 4842585
content-type:
audio/mpeg
content-disposition:
form-data; name="file2"; filename="away.mp3"
Name: comment
ContentType: null
Size: 7
content-disposition:
form-data; name="comment"
Notes:
1.
You can use request.getPart(name) to retrieve a
particular part with the given name attribute, instead
of request.getParts(), which retrieves all parts in a Collection<Part>.
2.
You can also use the following code to read the data from each part:
InputStream instream = request.getPart(part.getName()).getInputStream();
int byteRead;
while ((byteRead = instream.read()) != -1) {
out.write(byteRead);
}
Very useful information is given in simple text. Keep it up. Thank you so much.
ReplyDeleteThank you brother
ReplyDelete