1. Requirements:
1) A safer way to handle file upload by using commons-fileupload-1.3.jar provided by Apache Foundation.
2) Using simple JSP/Servlet for a simple mock up.
2. Preconditions:
1) Import related jars.
1) Import JRE-System-Library
2) Import J2EE 5.0 Library <jsp-api.jar, servlet-api.jar>
3) Import commons-io-2.4.jar
4) Import commons-fileupload-1.3.jar
2) Build a basic JavaWeb project.
1) Dir hierarchy is correctly configured
2) web.xml
3) index.jsp
3) Correctly deployed on Tomcat 6.x
3. Related Files
1) index.jsp
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form enctype="multipart/form-data" action="FileUploadServlet"
method="post">
File to upload: <input type="file" name="upfile" /><br /> Notes about
the file: <input type="text" name="note" /><br /> <br /> <input
type="submit" value="Upload" />
</form>
</body>
</html>
Comments:
1) Use basic Form for illustration. Pay attention to that enctype="multipart/form-data" must be point out.
2) web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>FileUploadServlet</servlet-name> <servlet-class>edu.xmu.servlet.FileUploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FileUploadServlet</servlet-name> <url-pattern>/FileUploadServlet</url-pattern> </servlet-mapping> </web-app>
Comments: Correctly mapping is essential!
3) edu.xmu.servlet.FileUploadServlet.java
package edu.xmu.servlet;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class FileUploadServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// TODO Auto-generated method stub
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// TODO Auto-generated method stub
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
System.out.println("isMultipart = " + isMultipart);
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set the repository to store temp files that uploaded.
File repository = new File("C:/YangKunLun/UploadRepository");
factory.setRepository(repository);
ServletFileUpload upload = new ServletFileUpload(factory);
try
{
List<FileItem> items = upload.parseRequest(req);
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext())
{
FileItem item = iter.next();
if (item.isFormField())
{
processFormField(item);
} else
{
processUploadedFile(item);
}
}
} catch (FileUploadException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("doPost");
}
private void processFormField(FileItem item)
{
String name = item.getFieldName();
String value = item.getString();
System.out.println("name = " + name + ", value = " + value);
}
private void processUploadedFile(FileItem item)
{
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
System.out.println("fieldName = " + fieldName + ", fileName = "
+ fileName + ", contentType = " + contentType
+ ", isInMemory = " + isInMemory + ", sizeInBytes = "
+ sizeInBytes);
}
}
Comments:
1) Output look like this:
isMultipart = true
fieldName = upfile, fileName = msvcr71.dll, contentType = application/x-msdownload, isInMemory = false, sizeInBytes = 348160
name = note, value = Hello
doPost
3) Enhanced edu.xmu.servlet.FileUploadServlet.java
package edu.xmu.servlet;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class FileUploadServlet extends HttpServlet
{
private final static String bufferPath = "C:/YangKunLun/UploadRepository";
private final static String destPath = "C:/YangKunLun/UploadStore";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// TODO Auto-generated method stub
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// TODO Auto-generated method stub
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
System.out.println("isMultipart = " + isMultipart);
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
File repository = new File(bufferPath);
factory.setRepository(repository); // Set the buffer directory.
factory.setSizeThreshold(1024 * 2); // Set the size of buffer.
ServletFileUpload upload = new ServletFileUpload(factory);
// Create a progress listener
ProgressListener progressListener = new ProgressListener()
{
private long megaBytes = -1;
/**
* pBytesRead: The total number of bytes, which have been read so
* far pContentLength: The total number of bytes, which are being
* read. May be -1, if this number is unknown. pItems : The number
* of the field, which is currently being read. (0 = no item so far,
* 1 = first item is being read, ...)
*/
public void update(long pBytesRead, long pContentLength, int pItems)
{
long mBytes = pBytesRead / 1000000;
// "if" statement is for the purpose of reduce the progress
// listeners activity
// For example, you might emit a message only, if the number of
// megabytes has changed:
if (megaBytes == mBytes)
{
return;
}
megaBytes = mBytes;
System.out.println("We are currently reading item " + pItems);
if (pContentLength == -1)
{
System.out.println("So far, " + pBytesRead
+ " bytes have been read.");
} else
{
System.out.println("So far, " + pBytesRead + " of "
+ pContentLength + " bytes have been read.");
}
}
};
upload.setProgressListener(progressListener);
try
{
List<FileItem> items = upload.parseRequest(req);
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext())
{
FileItem item = iter.next();
if (item.isFormField())
{
processFormField(item);
} else
{
processUploadedFile(item);
}
}
} catch (FileUploadException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("doPost");
}
private void processFormField(FileItem item)
{
String name = item.getFieldName();
String value = item.getString();
System.out.println("name = " + name + ", value = " + value);
}
private void processUploadedFile(FileItem item) throws Exception
{
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
System.out.println("fieldName = " + fieldName + ", fileName = "
+ fileName + ", contentType = " + contentType
+ ", isInMemory = " + isInMemory + ", sizeInBytes = "
+ sizeInBytes);
File fileToSave = new File(destPath, fileName);
item.write(fileToSave);
}
}
Output looks like this:
isMultipart = true
We are currently reading item 0
So far, 4096 of 20719060 bytes have been read.
We are currently reading item 1
So far, 1000042 of 20719060 bytes have been read.
We are currently reading item 1
So far, 2000084 of 20719060 bytes have been read.
We are currently reading item 1
So far, 3000126 of 20719060 bytes have been read.
We are currently reading item 1
So far, 4000168 of 20719060 bytes have been read.
We are currently reading item 1
So far, 5000210 of 20719060 bytes have been read.
We are currently reading item 1
So far, 6000252 of 20719060 bytes have been read.
We are currently reading item 1
So far, 7000294 of 20719060 bytes have been read.
We are currently reading item 1
So far, 8000336 of 20719060 bytes have been read.
We are currently reading item 1
So far, 9000378 of 20719060 bytes have been read.
We are currently reading item 1
So far, 10000420 of 20719060 bytes have been read.
We are currently reading item 1
So far, 11000462 of 20719060 bytes have been read.
We are currently reading item 1
So far, 12000504 of 20719060 bytes have been read.
We are currently reading item 1
So far, 13000546 of 20719060 bytes have been read.
We are currently reading item 1
So far, 14000588 of 20719060 bytes have been read.
We are currently reading item 1
So far, 15000630 of 20719060 bytes have been read.
We are currently reading item 1
So far, 16000672 of 20719060 bytes have been read.
We are currently reading item 1
So far, 17000714 of 20719060 bytes have been read.
We are currently reading item 1
So far, 18000756 of 20719060 bytes have been read.
We are currently reading item 1
So far, 19000798 of 20719060 bytes have been read.
We are currently reading item 1
So far, 20000840 of 20719060 bytes have been read.
fieldName = upfile, fileName = src.zip, contentType = application/x-zip-compressed, isInMemory = false, sizeInBytes = 20718763
name = note, value = Hello
doPost
Comments:
1) Added progress listener.
2) Added destination folder to verify output works.
P.S
Related sites:
1) http://commons.apache.org/proper/commons-fileupload/
2) http://commons.apache.org/proper/commons-fileupload/using.html