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进行判断
- if (ServletFileUpload.isMultipartContent(request)) {
- // 创建文件处理工厂,它用于生成 FileItem 对象。
- DiskFileItemFactory factory = new DiskFileItemFactory();
- 设置文件的缓存路径
- String tempdir =this.getServletContext().getRealPath("/upload/temp");
- java.io.File d = new java.io.File(savedir);
- if(!d.exists()){
- d.mkdirs();
- }
- factory.setSizeThreshold(1024*1024); // 设置最多只允许在内存中存储的数据,单位:字节
- factory.setRepository(d); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录(默认可以不用设置)
- // Create a new file upload handler
- ServletFileUpload upload = new ServletFileUpload(factory);
- // 设置允许用户上传文件大小,单位:字节
- upload.setSizeMax(yourMaxRequestSize);
- //上传文件,并解析出所有的表单字段,包括普通字段和文件字段
- List items = upload.parseRequest(request);
- //下面对每个字段进行处理,分普通字段和文件字段
- Iterator it = items.iterator();
- while(it.hasNext()){
- FileItem fileItem = (FileItem) it.next();
- //如果是普通字段
- if(fileItem.isFormField()){ //是普通的字段
- System.out.println(fileItem.getFieldName() + " " + fileItem.getName() + " " + new String(fileItem.getString().getBytes("iso8859-1"), "gbk"));
- fileItem.getFieldName();//得到字段name属性的值
- fileItem.getName();//得到file字段的文件名全路径名,如果不是file字段,为null
- fileItem.getString();//得到该字段的值,默认的编码格式
- fileItem.getString("UTF-8");//指定编码格式
- }else{//文件字段
- System.out.println(fileItem.getFieldName() + " " +
- fileItem.getName() + " " +//得到file字段的文件名全路径名
- fileItem.isInMemory() + " " +//用来判断FileItem类对象封装的主体内容是存储在内存中,还是存储在临时文件中,如果存储在内存中则返回true,否则返回false
- fileItem.getContentType() + " " +//文件类型
- fileItem.getSize()); //文件大小
- //什么东西都有了 ,想怎么处理都可以了
- //保存文件,其实就是把缓存里的数据写到目标路径下
- if(fileItem.getName()!=null && fileItem.getSize()!=0){
- File fullFile = new File(fileItem.getName());
- File newFile = new File("c:/temp/" + fullFile.getName());
- try {
- fileItem.write(newFile);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }else{
- System.out.println("文件没有选择 或 文件内容为空");
- }