一.基本原理
FileUpload组件将页面提交的所有元素(普通form表单域,如text和文件域file)都看作一样的FileItem,这样上传页面提交的request请求也就是一个FileItem的有序组合,FileUpload组件可以解析该request,并返回一个一个的FileItem。而对每一个FileItem,FileUpload组件可以判断出它是普通form表单域还是文件file域,从而根据不同的类型,采取不同的操作--如果是表单域,就读出其值,如果是文件域,就保存文件到服务器硬盘上或者内存中。
二.具体实现
对一个HttpRequest请求,我们要判断该请求是否是文件上传的请求
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
不过,个人觉得这个方法一般不需要,我们一般是在需要上传时才采用fileupload组件处理request请求的。
如果确实是文件上传的请求,我们如何解析该request呢?
// 创建一个基于磁盘的文件项目的工厂
FileItemFactory factory = new DiskFileItemFactory();
// 创建一个新的文件上传处理
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析请求 基于FileItem的List
List items = upload.parseRequest(request);
至此我们已经的到了FileItem的list,对每个Item的处理要考虑是标准的form表单域还是上传文件file域,然后做不同的处理,可以通过以下方式实现:
//处理上传的项目 循环输出list进行判断
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
//如果是form表单
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
对于一个简单的form表单域,我们可以通过以下方法得到该域的相关信息:
// 处理一个普通表单字段
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
...
}
而对于一个upload file,我们则可以通过如下方式得到其相关信息:
// 处理一个文件上传
if (!item.isFormField()) ...{
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
...
}
实际上,对于一个上传的文件,我们一般不会把它包存在内存中,除非它足够小。我们一般是把它保存到硬盘上,使用以下方法就可以将上传的文件保存到服务器硬盘上了:
File uploadedFile = new File(...);
item.write(uploadedFile);
三、更具体说明
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置最多只允许在内存中存储的数据,单位:字节
factory.setSizeThreshold(4096);
ServletFileUpload fu = new ServletFileUpload(factory);
fu.setSizeMax(100000);
// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
fu.setRepositoryPath(“D://Tomcat5//TEMP”);
//开始读取上传信息
List fileItems = fu.parseRequest(request);
// 依次处理每个上传的文件
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
//忽略其他不是文件域的所有表单信息
if (!item.isFormField()) {
String name = item.getName();
item.write(“D://UploadTest//”+ name);
这里在具体写得规范些,支持多文件上传
// 缓冲区大小,默认:10kb
private int sizeThreshold = 1024 * 10;
//设置最大文件大小:默认4M,为-1时表示无限制
private long sizeMax = 1024 * 1024 * 4;
// 字符编码,当读取上传表单的各部分时会用到该encoding
private String encoding = "utf-8";
// 保存普通form表单域
protected Map<String, String> parameters = new HashMap<String, String>();
// 保存上传的文件
private Map<String, FileItem> files = new HashMap<String, FileItem>();
// 所有文件的总大小
private long filesSize = 0;
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置最多只允许在内存中存储的数据,单位:字节
factory.setSizeThreshold(sizeThreshold);
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置允许用户上传文件大小,单位:字节
upload.setSizeMax(sizeMax);
upload.setHeaderEncoding(encoding);
File upDir= new File(uploadDir);
upDir.mkdirs();
//设置文件超出缓冲区时的存放目录
dsiFactory.setRepository(upDir);
try {
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
String fieldName = item.getFieldName();
String value = item.getString();
parameters.put(fieldName, value);
}
else {
String fieldName = item.getFieldName();
files.put(fieldName, item);
filesSize += item.getSize();
}
}
}
catch (FileUploadException e) {
e.printStackTrace();
}
}
if (files.isEmpty()) return;
for (String key : files.keySet()) {
FileItem item = files.get(key);
String filename = item.getName();
//提取名字
int lindex = fileName.lastIndexOf("//");
fileName = fileName.substring(lindex + 1);
File file = new File(路径);
item.write(file);
}