FileUpload组件将页面提交的所有元素(普通form表单域,如text和文件域file)都看作一样的FileItem,这样上传页面提交的request请求也就是一个FileItem的有序组合,FileUpload组件可以解析该request,并返回一个一个的FileItem。而对每一个FileItem,FileUpload组件可以判断出它是普通form表单域还是文件file域,从而根据不同的类型,采取不同的操作--如果是表单域,就读出其值,如果是文件域,就保存文件到服务器硬盘上或者内存中。
1.对一个HttpRequest请求,我们要判断该请求是否是文件上传的请求.
先确保该请求是一个文件上传的请求
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
2. 最简单的使用场景:
上传的文件只要是合理的小,就保存在内存中。
文件过大,应该写入硬盘的临时文件
不允许上传过大的文件。
// 创建文件处理工厂,它用于生成 FileItem 对象。
DiskFileItemFactory factory = new DiskFileItemFactory();
// 创建文件上传处理器
ServletFileUpload upload = new ServletFileUpload(factory);
// 处理请求
List /* FileItem */ items = upload.parseRequest(request);
请求处理的结果是一个文件列表,每一项实现FileItem接口。
3. 更多的控制:你可以简单的定制上传处理器或者文件处理工厂。
DiskFileItemFactory factory = new DiskFileItemFactory();
设置最多只允许在内存中存储的数据,单位:字节
factory.setSizeThreshold(yourMaxMemorySize);
设置一旦文件大小超过内存存储的值时,数据存放在硬盘的临时目录(默认可以不用设置)
factory.setRepository(yourTempDirectory);
设置允许用户上传文件大小,单位:字节
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(yourMaxRequestSize);
List /* FileItem */ items = upload.parseRequest(request);
4. 处理上传的项目
一旦完成分析,你就会获得要处理的项目列表。通常情况下,你会将普通字段和文件字段区别开。
对每个Item的处理要考虑是标准的form表单域还是上传文件file域,然后做不同的处理.
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
如果是普通字段,大部分情况只对它的项目名称以及字符串值感兴趣。
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
...
}
实际上,对于一个上传的文件,我们一般不会把它包存在内存中,除非它足够小。我们一般是把它保存到硬盘上,使用以下方法就可以将上传的文件保存到服务器硬盘上了:
if (writeToFile) {
File uploadedFile = new File(...);
item.write(uploadedFile);
} else {
InputStream uploadedStream = item.getInputStream();
...
uploadedStream.close();
}
注意:在FileUpload的默认实现中,如果数据已经在临时文件中,write()会尝试重命名文件到指定的目录。
如果你确定要访问内存中的上传数据,只要调用get()方法来获得bytes数组类型的数据。
// Process a file upload in memory
byte[] data = item.get();
5. 资源清理
如果在处理之前,你把上传的文件保存在临时文件中。如果这些临时文件没用了,需要自动删除。这是靠一个不断重复的线程进行处理的 。 org.apache.commons.io.FileCleaner 需要在web.xml中增加以下代码
<web-app>
...
<listener>
<listener-class>
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
...
</web-app>
6. 创建DiskFileItemFactory
FileCleanerCleanup提供一个org.apache.commons.io.FileCleaningTracker的实例。在创建
DiskFileItemFactory时,必须使用这个实例。
public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context, File repository) {
FileCleaningTracker fileCleaningTracker = FileCleanerCleanup.getFileCleaningTracker(context);
DiskFileItemFactory factory
= new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository);
factory.setFileCleaningTracker(fileCleaningTracker);
return factory;
}
表单中设置 enctype="multipart/form-data" 很重要。
处理上传jsp文件
判断表单是否是Multipart类型的。这里可以直接对request进行判断