流程
文件上传除了Servlet和jsp依赖的jar包外,还需要额外导入commons-fileupload和commons-io包
过程:
表单提交——>判断表单是否带文件——>是的话,创建保存文件的目录——>创建DiskFileItemFactory工厂,设置阈值,超过阈值转存到临时文件目录——>创建ServletFileUpload,可以设置监听器、编码、可上传文件大小——>servletFileUpload解析请求,获得封装好的FileItem对象——>对于文件对象,创建唯一的UUID目录,将文件转为输入流,通过FileOutputStream写到指定地址
1、表单设置enctype="multipart/form-data"可以用来支持文件上传
2、ServletFileUpload对象可以用来处理请求,将表单数据封装成一个个FileItem对象。创建ServletFileUpload时需要DiskFileItemFactory 对象,也可以通过set的方式设置。
3、为了保证安全,上传的文件应该放在外界无法直接访问的目录下,比如WEB-INF下
4、为防止上传文件覆盖,应该创建唯一的文件夹 UUID.randomUUID().toString()
5、可以给DiskFileItemFactory对象设置个阈值,超过阈值就将文件放入另一个文件夹(缓存,可以过段时间删除)
6、设置上传文件的最大值
7、可以对文件后缀进行检测,判断是否接收
代码
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 通过表单上传文件 get上传文件有限制 post没有--%>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file2"></p>
<p><input type="submit"> | <input type="reset"></p>
</form>
</body>
</html>
FileServlet
public class FileServlet extends javax.servlet.http.HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断上传文件的方式是不是post,文件是普通表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(req)) {
return; //如果不符合,就return中止
}
//创建文件上传的保存路径,建议在WEB-INF下面,这样用户无法直接访问
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadfile = new File(uploadPath);
if (!uploadfile.exists()) { //文件不存在,就建立一个
uploadfile.mkdir();
}
//缓存。如果文件大小超过预期,就将文件放在一个临时文件中,过几天删除,或者提醒用户转为永久
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tempfile = new File(tempPath);
if (!tempfile.exists()) {
tempfile.mkdir();
}
//处理上传文件,一般都需要通过流来获取。我们可以使用原生态的request.getInputStream获取流,
// 但是太麻烦了。因此使用Apache文件上传组件来实现。使用common-fileupload,它依赖于commons-io组件
try {
//1、创建DiskFileItemFactory工厂,设置阈值,超过阈值转存临时文件
DiskFileItemFactory factory = getDiskFileItemFactory(tempfile);
//2、获取ServletFileUpload,可以设置监听器、编码、可上传文件大小
ServletFileUpload servletFileUpload = getServletFileUpload(factory);
//3、上传文件
String msg = uploadParseRequest(servletFileUpload, req, uploadPath);
//上传完消息传回前端
req.setAttribute("msg", msg);
req.getRequestDispatcher("/info.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
public static DiskFileItemFactory getDiskFileItemFactory(File file) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//缓冲区阈值,超过这个阈值,就将文件放入临时文件中
factory.setSizeThreshold(1024*1024);
//设置临时目录
factory.setRepository(file);
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
//获取ServletFileUpload
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
//设置监听器
servletFileUpload.setProgressListener(new ProgressListener() {
@Override
public void update(long l, long l1, int i) {
System.out.println("总大小:" + l1 + " 已上传:" + l);
}
});
//处理乱码问题
servletFileUpload.setHeaderEncoding("utf-8");
//设置单个文件的最大大小
servletFileUpload.setFileSizeMax(1024 * 1024 * 10);
//设置总文件的最大大小
servletFileUpload.setSizeMax(1024 * 1024 * 10);
return servletFileUpload;
}
public static String uploadParseRequest(ServletFileUpload servletFileUpload, HttpServletRequest request, String uploadPath)
throws Exception {
String msg = "";
//解析请求,并封装为FileItem对象
List<FileItem> fileItems = servletFileUpload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
//普通的表单字段
//getFieldName是获得控件的名字,getName是获得传入的文件的名字。因此对于普通的表单字段,getName()为null
String fieldname = fileItem.getFieldName(); //前端控件的名字
String value = fileItem.getString("utf-8"); //获取String值
System.out.println(fieldname + " " + value);
} else {
//====================处理文件名======================
String name = fileItem.getName();
System.out.println(name);
//名字不符合就下一个
if (name.trim().equals("") || name == null) {
continue;
}
//获取最后的文件名
String filename = name.substring(name.lastIndexOf('/') + 1);
//获取后缀
String type = name.substring(name.lastIndexOf('.' )+1);
System.out.println("文件信息[文件名:" + filename + " 类型:" + type);
//UUID保证文件名唯一
String uuid = UUID.randomUUID().toString();
//====================设置存放地址======================
//文件真实存放目录
String path = uploadPath + "/" + uuid;
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
//====================传输======================
//获取文件输入流
InputStream inputStream = fileItem.getInputStream();
//获取文件输出流
FileOutputStream outputStream = new FileOutputStream(path + "/" + filename);
//设置缓冲区
byte[] buffer = new byte[2048];
//读写
int len = 0;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len); //取buffer中的0到len
}
inputStream.close();
outputStream.close();
}
msg = "上传成功";
}
return msg;
}
}
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
web.xml
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.yuan.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>