使用servlet3.1注解实现文件上传详细例子
之前的使用servlet3.0实现文件上传的文章中有一些不太完善的地方,所以写这篇文章完善一下。
上传是文件名重复的问题
下面代码是之前servlet3.0实现文件上传的文章中的上传方式:
/**
* 处理上传的servlet
*/
@WebServlet("/upload")
@MultipartConfig //表示当前servlet可以处理multipart请求
public class UploadServlet01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取服务器存放上传文件的路径
String path = this.getServletContext().getRealPath("/upload");
System.out.println(path);
//获取上传文件,photo是html表单中的name
Part part = request.getPart("photo");
//获取上传文件的名称,这是servlet3.1中加入的方法
String fileName = part.getSubmittedFileName();
System.out.println(path + "/" + fileName);
//将上传的文件写入到指定的服务器路径中
part.write(path + "/" + fileName);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
上面代码中有可能会出现多个用户上传的文件名重复的情况,此时之前在服务器中存储的文件会被后上传的同名文件替换掉,为了解决这个问题,可以将文件名修改一下,建议使用UUID的方式重命名。
uuid是Universally Unique Identifier的缩写,中文是通用统一识别码,uuid具有唯一性,uuid的生成跟系统的时间、mac地址、时间序列、随机数有关,所以通常所生成的uuid是不会重复的,两个相同的uuid出现的概率非常低(比陨石撞击地球的概率还要低)。
//获取上传文件的名称,这是servlet3.1中加入的方法
String fileName = part.getSubmittedFileName();
//在文件名中添加uuid
fileName = UUID.randomUUID() + "_" + fileName;
通过上面的代码就可以确保用户上传文件名的唯一性了。
创建目录便于管理
如果用户上传的文件都放到一个文件夹下的话,随着时间的积累,该文件夹就会变的非常臃肿,不利于管理。因此,这里考虑将用户上传的文件放到不同的文件夹中,我们来按照年、月、日创建多级子目录的方式。比如用户在2018年1月25日上传了一个文件monkey.jpg,那就让该文件放到这样的文件夹目录中:/2018/1/25/monkey.jpg
//获取当前系统时间的年月日
LocalDate now = LocalDate.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
String path = this.getServletContext().getRealPath("/upload");
//在upload下分别创建年、月、日三级子目录
path = path + "/" + year + "/" + month + "/" +day;
//创建父目录
File parentDir = new File(path);
//如果父目录不存在,则创建
if(!parentDir.exists()){
parentDir.mkdirs();
}
修改后的代码:
/**
* 处理上传的servlet
*/
@WebServlet("/upload")
@MultipartConfig //表示当前servlet可以处理multipart请求
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取服务器存放上传文件的路径
String path = this.getServletContext().getRealPath("/upload");
System.out.println(path);
//获取上传文件,photo是html表单中的name
Part part = request.getPart("photo");
//获取上传文件的名称,这是servlet3.1中加入的方法
String fileName = part.getSubmittedFileName();
//在文件名中添加uuid
fileName = UUID.randomUUID() + "_" + fileName;
//获取当前系统时间的年月日
LocalDate now = LocalDate.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
//在upload下分别创建年、月、日三级子目录
path = path + File.separator + year + File.separator + month + File.separator +day;
//创建父目录
File parentDir = new File(path);
//如果父目录不存在,则创建
if(!parentDir.exists()){
parentDir.mkdirs();
}
//将上传的文件写入到指定的服务器路径中
part.write(path + File.separator + fileName);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
设置上传文件的大小
在@MultipartConfig注解中有两个属性:
maxFileSize:表示上传一个文件的最大值,单位是byte
maxRequestSize:表示一次请求中上传文件的最大值,一次可能上传多个文件,这些文件大小的之和。单位是byte
如果上传的文件超出了设置的最大值时,系统会在
Part part = request.getPart("photo");
抛出一个IllegalStateException的异常,我们可以通过捕获该异常从而向用户提示友好信息。
/**
* 处理上传的servlet
*/
@WebServlet("/upload")
@MultipartConfig(maxFileSize = 1024*5) // 表示当前servlet可以处理multipart请求
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static MultipartConfig config = UploadServlet.class.getAnnotation(MultipartConfig.class);
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 获取服务器存放上传文件的路径
String path = this.getServletContext().getRealPath("/upload");
System.out.println(path);
// 获取上传文件,photo是html表单中的name
Part part;
try{
part = request.getPart("photo");
}catch(IllegalStateException e){
//上传的单个文件超出maxFileSize或者上传的总的数据量超出maxRequestSize时会抛出此异常
e.printStackTrace();
out.write("文件上传失败,请上传小于5kb的文件");
return;
}
// 获取上传文件的名称,这是servlet3.1中加入的方法
String fileName = part.getSubmittedFileName();
// 在文件名中添加uuid
fileName = UUID.randomUUID() + "_" + fileName;
// 获取当前系统时间的年月日
LocalDate now = LocalDate.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
// 在upload下分别创建年、月、日三级子目录
// path = path + "/" + year + "/" + month + "/" +day;
path = path + File.separator + year + File.separator + month + File.separator + day;
// 创建父目录
File parentDir = new File(path);
// 如果父目录不存在,则创建
if (!parentDir.exists()) {
parentDir.mkdirs();
}
System.out.println(path);
// 将上传的文件写入到指定的服务器路径中
part.write(path + File.separator + fileName);
out.write("文件上传成功!");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}