两个依赖包
commons-fileupload-1.3.2、commons-io-2.5.jar。
可以从官网下载最新版本commons-fileupload、commons-io
注意事项
-
表单 enctype 属性应该设置为 multipart/form-data
enctype 决定了表单打包数据文件的方式,有如下几种取值:
a. application/x-www-form-urlencoded。默认的编码方式。但是在用文本的传输和MP3等大型文件的时候,使用这种编码就显得 效率低下。
b. multipart/form-data 。 指定传输数据为二进制类型,比如图片、mp3、文件。
c. text/plain。纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。
默认方式不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。 -
表单method属性必须是post
a. method=’get’ 编码后的表单内容附加在请求连接后
b. method=’post’ 编码后的表单内容作为post请求的正文内容
get方法会导致将文件加到url后面,这里必须要用posts
核心API
1. DiskFileItemFactory
a. setSizeThreshold(int sizeThreshold) :设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时,fileupload组件将使用临时文件缓存上传文件。
b. setRepository(Java.io.File repository) :指定临时文件目录,默认值为System.getProperty(“java.io.tmpdir”).
2. ServletFileUpload:
a. isMultipartContent(request):检测是否为多媒体上传 判断enctype属性是否为multipart/form-data
b. setFileSizeMax(long fileSizeMax) :设置上传文件的最大值(单个文件),用于设置单个上传文件的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。
c. setSizeMax(long sizeMax) :设置上传文件总量的最大值(所有上传文件),用于设置请求消息实体内容(即所有上传数据)的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。
d. setHeaderEncoding(java.lang.String encoding) :设置编码格式。在文件上传请求的消息体中,除了普通表单域的值是文本内容以外,文件上传字段中的文件路径名也是文本,在内存中保存的是它们的某种字符集编码的字节数组,Apache文件上传组件在读取这些内容时,必须知道它们所采用的字符集编码,才能将它们转换成正确的字符文本返回
e. List parseRequest(HttpServletRequest request):解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合
3. FileItem
a. isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回false。
实现步骤
- 创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录。
- 使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
- 调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
- 对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件:若是则上传
代码实现
结构图:
upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传练习</title>
</head>
<body>
<form action="UploadServlet" method="post" enctype="multipart/form-data">
选择一个文件<br>
<input type="file" name="filename"><br>
<br>
<br>
<input type="submit" value="提交">
</form>
</body>
</html>
UpLoadServlet.java
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
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 UploadServlet
*/
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String Upload_Directory = "upload";
private static int Max_sizeThreshold=1024 * 1024 * 3;
private static int Max_filesize=1024 * 1024 * 3;
private static int Max_size=1024 * 1024 * 3;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//检测是否为多媒体上传 判断enctype属性是否为multipart/form-data
if(!ServletFileUpload.isMultipartContent(request)){
//不符合条件 停止上传
System.out.println("Error:上传失败,表单必须包含 enctype=multipart/form-data");
PrintWriter writer=response.getWriter();
writer.println("Error:上传失败,表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
//配置上传参数
DiskFileItemFactory factory=new DiskFileItemFactory();
//设置缓冲区大小
factory.setSizeThreshold(Max_sizeThreshold);
//设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload=new ServletFileUpload(factory);
//最大文件上传值(文件大小限制)
upload.setFileSizeMax(Max_filesize);
//最大上传数(请求数)
upload.setSizeMax(Max_size);
upload.setHeaderEncoding("UTF-8");
//构造临时路径路径,即相对于当前应用的目录
String uploadpath=request.getServletContext().getRealPath("/")+Upload_Directory;
File uploadDir=new File(uploadpath);
if(!uploadDir.exists()){
uploadDir.mkdir();//不存在该路径 则创建
}
try {
//解析请求内容 提取文件数据
List<FileItem> formItems=upload.parseRequest(request);
if(formItems !=null && formItems.size()>0){
for(FileItem item:formItems){
//判断是普通文本表单字段,还是一个文件表单字段
if(!item.isFormField()){
//是文件时
String filename=new File(item.getName()).getName();
String filepath=uploadpath + File.separator + filename;
File storeFile = new File(filepath);
System.out.println(filepath);
item.write(storeFile);
request.setAttribute("message", "文件上传成功");
}
}
}
} catch (Exception e) {
request.setAttribute("message", "错误信息"+e.getMessage());
}
request.getServletContext().getRequestDispatcher("/message.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
如果不是直接添加的servlet文件,那么还需要自己在配置文件web.xml内添加如下代码
<servlet>
<description></description>
<display-name>UploadServlet</display-name>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/UploadServlet</url-pattern>
</servlet-mapping>
message.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传结果</title>
</head>
<body>
<center>
<h2>${message}</h2>
</center>
</body>
</html>
个人疑惑点知识拓展
-
System.getProperty(“java.io.tmpdir”):输出的是系统的临时目录
一般情况下(不再服务器内发布,即普通的java工程的main里面),对应的临时路径为:win:C\Users\用户名\AppData\Local\Temp
当程序在Tomcat下时,该路径变为tomcat安装目录下的temp文件,我的对应为:D:\Eclipse01\apache-tomcat-7.0.52\temp -
跨平台使用绝对路径利用File.separator
File.separator 的作用相当于 ’ \ ',windows系统下能识别但是 Linux 中不识别 ’ \ ’ ,而 File.separator 是系统默认的文件分隔符号,在任何系统中使用都不会出错 -
将文件上传到项目目录里面而非服务器目录的方法:在\tomcat-7.0.23\conf\server.xml 文件里配置文件设置虚拟目录
具体实现参考:Tomcat学习笔记(三)——虚拟目录及虚拟子目录篇