首先需要注意的问题:
1 . form表单的内容格式要定义成multipart/form-data格式.
2 . 需要导入类库:
commons-fileupload-x.x.x.jar (下载地址:http://commons.apache.org/proper/commons-fileupload/)
commons-io-x.x.jar (下载地址:http://commons.apache.org/proper/commons-io/)
使用开源Apache commons fileupload包上传文件大概步骤如下:
1 . 创建文件解析对象
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
sfu.setHeaderEncoding("utf-8"); //设置编码
sfu.setFileSizeMax(1024*1024*1); //设置单个上传文件最大字节数
sfu.setSizeMax(1024*1024*10); //设置整个表单最大字节数
2 . 创建一个集合保存表单数据
List<FileItem> formList = sfu.parseRequest(request);
3 . 读取表单内容
for (FileItem fileItem: formList) {
//表单控件name属性值
String fieldName = fileItem.getFieldName();
System.out.println("========控件名称 : " + fieldName + "========");
if (fileItem.isFormField()) { //检测表单类型 true:普通表单 false:表单包含文件数据
String fieldValue = fileItem.getString();
fieldValue = new String(fieldValue.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("普通内容:" + fieldName + "=" + fieldValue);
} else {
String fileName = fileItem.getName();
long fileSize = fileItem.getSize();
File uploadFile = new File(saveDir, fileName);
fileItem.write(uploadFile);//保存上传文件
System.out.println("文件名 : " + fileName);
System.out.println("文件大小 : " + fileSize + "byte");
System.out.println("文件保存路径 : " + savePath);
}
}
具体事例如下:
1 . 源代码
FileUpload.html
<!DOCTYPE html>
<head>
<title>testUpload</title>
<meta charset="utf-8">
</head>
<body>
<h3>文件上传</h3>
<form enctype="multipart/form-data" method="post" action="FileUpload">
文件描述:<input type="text" name="text" /><br/>
选择文件:<input type="file" name="file1" /><br/>
<input type="submit" value="上传" />
</form>
</body>
FileUpload.java
package cn.iborder.upload;
import java.io.File;
import java.io.IOException;
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;
/**
* Servlet implementation class FileUpload
*/
public class FileUpload extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public FileUpload() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setCharacterEncoding("UTF-8");
response.getWriter().println("请以POST方式上传文件");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//保存路径
String savePath = getServletContext().getRealPath("/temp1");
File saveDir = new File(savePath);
if (!saveDir.exists()) {
saveDir.mkdir();
}
//创建核心上传类实例
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
sfu.setHeaderEncoding("utf-8"); //设置编码
sfu.setFileSizeMax(1024*1024*1); //设置单个上传文件最大字节数
sfu.setSizeMax(1024*1024*10); //设置整个表单最大字节数
//读取表单数据
try {
List<FileItem> formList = sfu.parseRequest(request);
for (FileItem fileItem : formList) {
//表单控件name属性值
String fieldName = fileItem.getFieldName();
System.out.println("========控件名称 : "+fieldName+"========");
if(fileItem.isFormField()){ //检测表单类型 true:普通表单 false:表单包含文件数据
String fieldValue = fileItem.getString();
fieldValue = new String(fieldValue.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("普通内容:" + fieldName + "=" + fieldValue);
}else{
String fileName = fileItem.getName();
long fileSize = fileItem.getSize();
File uploadFile = new File(saveDir, fileName);
fileItem.write(uploadFile); //保存上传文件
System.out.println("文件名 : "+fileName);
System.out.println("文件大小 : "+fileSize+"byte");
System.out.println("文件保存路径 : "+savePath);
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
System.out.println("获取表单内容失败!");
System.out.println(e.getMessage());
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("保存上传文件失败!");
System.out.println(e.getMessage());
}
}
}
2 . 运行结果
相关类说明:
将请求消息实体中的每一个项目封装成单独的DiskFileItem (FileItem接口的实现) 对象的任务
由 org.apache.commons.fileupload.FileItemFactory 接口的默认实现
org.apache.commons.fileupload.disk.DiskFileItemFactory 来完成。当上传的文件项目比较小时,直接保存在内存中(速度比较快),比较大时,以临时文件的形式,保存在磁盘临时文件夹(虽然速度慢些,但是内存资源是有限的)。
构造方法
1) public DiskFileItemFactory()
采用默认临界值和系统临时文件夹构造文件项工厂对象。
2) public DiskFileItemFactory(int sizeThreshold,File repository)
采用参数指定临界值和系统临时文件夹构造文件项工厂对象。
2 . ServletFileUpload 类
org.apache.commons.fileupload.servlet.ServletFileUpload类是Apache文件上传组件处理文件上传的核心高级类(所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)。
使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
如果你希望进一步提高新能,你可以采用 getItemIterator 方法,直接获得每一个文件项的数据输入流,对数据做直接处理。
在使用ServletFileUpload对象解析请求时需要根据DiskFileItemFactory对象的属性sizeThreshold(临界值)和repository(临时目录)来决定将解析得到的数据保存在内存还是临时文件中,如果是临时文件,保存在哪个临时目录中?。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
3 . FileItem类
文件上传时需要用到FileItem类,FileItem是一个接口,它的实现类是DiskFileItem。常用方法如下:
1)boolean isFormField()。isFormField方法用来判断FileItem对象里面封装的数据是一个普通文本表单字段,还是一个文件表单字段。如果是普通文本表单字段,返回一个true否则返回一个false。因此可以用该方法判断是否是普通表单域还是文件上传表单域。
2)String getName()。getName方法用来获得文件上传字段中的文件名。
3)String getFieldName()。getFieldName方法用来返回表单标签的name属性的值。
4)void write(File file)。write方法将FileItem对象中的内容保存到某个指定的文件中。如果FileItem对象中的内容是保存在某个临时文件中,该方法完成后,临时文件可以会被删除。该方法也可以将普通表单字段保存在一个文件中,但最主要的用途是把上传的文件内容保存在本地文件系统中。
5)String getString()。getString()方法将FileItem对象中保存的数据流内容以一个字符串返回。它有两个重载形式。public java.lang.String getString()和public java.lang.String getString(java.lang.String encodeing) throws java.io.UnsupportedEncodingException。前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码。如果在读取普通表单字段元素的内容时,出现了乱码现象,可以调用第二个方法,并传入 正确的字符集编码名称。
6)String getContentType()。此方法用来获得上传文件的类型,即标段字段元素描述头属性“content-type”的值,如image/jpeg。如果FileItem对象对应的是普通的表单字段,将返回null。
7)boolean isInMemory()。判断FileItem对象封装的数据是保存在内存中还是硬盘中。
8)void delete()。此方法用来清空FileItem对象中封装的主体内容,如果内容是被保存在临时文件中,该方法会把临时文件删除。
9)InputStream getInputStream()。以流的形式返回上传文件的主体内容。
10)long getSize()。返回上传文件的大小。