简介
之前的使用servlet3.0实现文件上传的文章中有一些不太完善的地方,所以写这篇文章完善一下。
上传是文件名重复的问题
下面代码是之前servlet3.0实现文件上传的文章中的上传方式:
package com.monkey1024.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
/**
* 处理上传的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();
}
修改后的代码:
package com.monkey1024.servlet;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**
* 处理上传的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的异常,我们可以通过捕获该异常从而向用户提示友好信息。
package com.monkey1024.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDate;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**
* 处理上传的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);
}
}
多文件上传
用户在客户端有时需要进行多文件上传,此时可以通过下面方法获取Part对象的集合:
Collection<Part> parts = request.getParts();
然后遍历该集合分别处理part对象即可:
package com.monkey1024.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDate;
import java.util.Collection;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**
* 处理上传的servlet
*/
@WebServlet("/upload")
@MultipartConfig(maxRequestSize = 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);
// 一次上传多个文件
Collection<Part> parts;
try {
parts = request.getParts();
} catch (IllegalStateException e) {
// 上传的单个文件超出maxFileSize或者上传的总的数据量超出maxRequestSize时会抛出此异常
e.printStackTrace();
out.write("文件上传失败,请上传小于5kb的文件");
return;
}
// 获取当前系统时间的年月日
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();
}
for (Part part : parts) {
// 获取上传文件的名称,这是servlet3.1中加入的方法
String fileName = part.getSubmittedFileName();
if("".equals(fileName)) {
//如果文件名为"",说明这个文件是空,无需进行上传处理
continue;
}
// 在文件名中添加uuid
fileName = UUID.randomUUID() + "_" + fileName;
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);
}
}
bootstrap-fileupload组件
如果希望实现一些更炫的前端效果,可以借助使用bootstrap-fileupload,该组件基于bootstrap实现,使用前需要引入bootstrap相关文件,里面的文档和demo都非常丰富,感兴趣的同学可以自行查看。 在线文档:http://plugins.krajee.com/file-input 在线demo:http://plugins.krajee.com/file-input/demo
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~