首先,需要导入common-io和common-fileupload两个jar包
编写servlet
package org.westos.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 通过ServletFileUpload判断用户的请求是普通表单还是带文件的表单
if(!ServletFileUpload.isMultipartContent(request)){
//如果是普通表单,直接返回
return;
}
//2.1创建文件的保存路径,建议保存在WEB-INF路径下,比较安全,用户无法直接访问该路径下的文件
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if(!uploadFile.exists()){
//如果目录不存在,就创建这个目录
uploadFile.mkdir();
}
//2.2创建临时路径,如果文件超过了预期的大小,将它先放到临时路径下,完成上传后,删除临时文件
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File tmpFile = new File(tmpPath);
if(!tmpFile.exists()){
//如果不存在,就创建
tmpFile.mkdir();
}
//-------------------------完成路径的创建----------------------
/*
* 3、使用DiskFileItemFactory加工临时文件的保存目录:
* 如:做处理文件上传路径和限制文件大小的加工
* 一般来说,可以通过流来获取,如request.getInputStream(),
* 但是,采用原生态的流获取文件十分麻烦
* 因此,我们使用Apache的文件上传组件common-fileupload来实现,这个组件依赖于common-io组件。
* */
//3.1 创建DiskFileItemFactory对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//3.2 通过工厂设置缓存区,上传文件大于缓存区时,将该文件先存至临时文件中
factory.setSizeThreshold(1024*1024);//缓存区大小为1M
//设置临时文件的保存目录,需要传入临时文件的目录
factory.setRepository(tmpFile);
//------------------------完成文件目录的加工---------------------------
/*
* 4、使用ServletFileUpload处理上传文件
* ServletFileUpload对象负责处理上传的文件,并将文件封装为FileItem对象
* 在使用ServletFileUpload对象解析请求时需要传入DiskFileItemFactory对象
* */
//4.1获取ServletFileUpload对象(需要传入工厂对象)
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//4.2监听文件的上传进度
fileUpload.setProgressListener(new ProgressListener() {
@Override
//pBytesRead 已经读取到的文件的大小
//pContentLength 文件大小
public void update(long pBytesRead, long pContentLength, int pItem) {
System.out.println("文件大小:"+pContentLength+" 已上传"+pBytesRead);
}
});
//4.3 处理乱码问题,设置编码格式
fileUpload.setHeaderEncoding("UTF-8");
//4.4 设置上传文件的的最大值,单位bit
fileUpload.setFileSizeMax(1024*1024*100);
//4.4 设置上传总文件的最大值
fileUpload.setSizeMax(1024*1024*100);
//4.6 解析前端请求,并将其封装为FileItem对象
/*FileItem对象: 使用ServletFileUpload对象的parseRequest(Request)方法
可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,
然后以List列表的形式返回。*/
try {
List<FileItem> fileItems = fileUpload.parseRequest(request);
for (FileItem fileItem : fileItems) {
//带文件的表单也存在不是文件的表单项
//isFormField();判断上传的文件是普通的表单还是带文件的表单
if(fileItem.isFormField()){
String name = fileItem.getFieldName();//用于返回表单标签name属性的值
String value = fileItem.getString("UTF-8");//将FileItem对象中保存的数据流内容以一个字符串返回
System.out.println(name+":"+value);
}else{
String upLoadFileName = fileItem.getName();//获得文件上传字段中的文件名
System.out.println(""+upLoadFileName);
if(upLoadFileName.trim().equals("")||upLoadFileName==null){
continue;//文件名不存在或为空串,无法保存
}
//获得上传的文件名 假设选择上传文件时文件的路径为/xxx/xxx/xxx.jpg
String fileName = upLoadFileName.substring(upLoadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
/*
获取文件后缀名的应用:
如果文件后缀名不是网站所要求的文件类型,可以直接return,
然后通知用户文件类型不正确
*/
String fileExtName = upLoadFileName.substring(upLoadFileName.lastIndexOf(".")+1);
System.out.println("上传的文件为:"+fileName+" 文件类型:"+fileExtName);
/*
为了保证文件路径名唯一使用UUID(唯一识别通用码),还可以使用日期区分
UUID.randomUUID(); 随机产生一个唯一识别的通用码
*/
//创建文件的路径名
String uuidPathName = UUID.randomUUID().toString();
//------------------完成文件处理-------------------------
//5、为每个文件创造存储目录
//给每个文件创建一个对应的目录,
//文件将存储在uploadPath目录下的uuidPathName目录下
String realPath = uploadPath+"/"+uuidPathName;
File realPathFile = new File(realPath);
if (!realPathFile.exists()){
realPathFile.mkdir();
}
//-------------------完成文件的保存-----------------------
//6、传输文件内容
//6.1 获得上传文件的流
InputStream inputStream = fileItem.getInputStream();
//6.2 创建文件输出流(写入文件内容)
FileOutputStream outputStream = new FileOutputStream(realPath+"/"+fileName);
//6.3 创建一个缓冲区
byte[] buffer = new byte[1024*8];
//6.4 判断是否读取完毕
int len = 0;
if ((len=inputStream.read(buffer))>0){
outputStream.write(buffer,0,len);
}
//6.5 关闭流
inputStream.close();
outputStream.close();
//6.6 清除临时文件
fileItem.delete();
//------------------------完成文件的传输-------------------------
//7、返回文件上传结果
request.setAttribute("msg","上传成功!");
request.getRequestDispatcher("info.jsp").forward(request,response);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
request.setAttribute("msg","上传失败!");
request.getRequestDispatcher("info.jsp").forward(request,response);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
request.setAttribute("msg","上传失败!");
request.getRequestDispatcher("info.jsp").forward(request,response);
} catch (IOException e) {
e.printStackTrace();
request.setAttribute("msg","上传失败!");
request.getRequestDispatcher("info.jsp").forward(request,response);
}
}
}
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>org.westos.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
</web-app>
编写jsp
<%--
Created by IntelliJ IDEA.
User: 1
Date: 2019/7/20
Time: 9:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<%--1.method必须为post,get无法获取大数据
2.enctype="multipart/form-data 表示表单中存在数据上传--%>
<div>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
<p>用户名:<input type="text" name="username"></p>
<p>选择文件:<input type="file" name="file"></p>
<p><input type="submit" value="上传文件"></p>
</form>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>提示信息</title>
</head>
<body>
${pageContext.request.getAttribute("msg")}
</body>
</html>
运行,打开注册界面
控制台输出
可以看到,已经上传到创建的文件夹里