实现头像上传
- 自定义封装响应服务器数据
- 自己创建一个Controller接口
- 自定义控制器对象父类
- 自己创建核心控制器
- 封装一个文件上传的公共类
- servlet获取上传的图片
- servlet删除无效的图片
- javaScript实现相关的功能
一、自定义封装响应服务器数据
package cms.project.dom.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/***
* @Date(时间)2023-05-05
* @Author 半杯可可
*
* 用于封装响应服务器数据
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseData {
/**
* 响应代码
*/
private int code;
/**
* 响应消息
*/
private String msg;
/**
* 响应数据
*/
private Object data;
}
二、自己创建一个Controller接口
package cms.project.dom.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/***
* @Date(时间)2023-05-11
* @Author 半杯可可
*
*
* 对客户端发起请求,进行抽象接口的处理
*/
public interface Controller {
/***
* 核心方法
* @param request 发起请求
* @param response 响应数据
* @throws ServletException
* @throws IOException
*/
void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
三、自定义控制器对象父类
package cms.project.dom.servlet;
import cms.project.dom.util.PageVo;
import cms.project.dom.util.ResponseData;
import com.google.gson.GsonBuilder;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/***
* @Date(时间)2023-05-11
* @Author 半杯可可
*
*
* 所有自定义控制器对象的父类 - 相关的公共操作的提取到父类,便于代码的重用
*
* servlet 简单封装
*/
public abstract class BaseController implements Controller{
/**
* 成功响应的封装 - 默认
*
* @param data
* @return
*/
public ResponseData successJson(Object data) {
return new ResponseData(200, "", data);
}
/**
* 重载方法 - 封装所有的成功响应信息
*
* @param code
* @param msg
* @param data
* @return
*/
public ResponseData successJson(Integer code, String msg, Object data) {
return new ResponseData(code, msg, data);
}
/**
* 错误响应的封装 - 默认
*
* @param msg
* @return
*/
public ResponseData errorJson(String msg) {
return new ResponseData(500, msg, null);
}
/**
* 重载方法 - 封装所有的错误响应信息
*
* @param code
* @param msg
* @param data
* @return
*/
public ResponseData errorJson(Integer code, String msg, Object data) {
return new ResponseData(code, msg, data);
}
/**
* 响应 JSON 字符串到客户端浏览器中
*
* @param resp
* @param responseData
* @throws IOException
*/
protected void print(HttpServletResponse resp, ResponseData responseData)
throws IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.print(new GsonBuilder()
.setDateFormat("yyyy-MM-dd hh:mm:ss.SSS")
.create()
.toJson(responseData));
out.flush();
out.close();
}
/**
* 封装PageVo - 用于 LayUI 分页
*
* @param count
* @param data
* @return
*/
protected PageVo pageVo(Long count, Object data) {
PageVo vo = new PageVo();
vo.setCode(0);
vo.setCount(count);
vo.setData(data);
return vo;
}
}
四、自己创建核心控制器
package cms.project.dom.servlet;
import cms.project.dom.util.ResponseData;
import com.google.gson.GsonBuilder;
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 java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/***
* @Date(时间)2023-05-05
* @Author 半杯可可
*
* 核心控制器
*/
@WebServlet(urlPatterns = "/", loadOnStartup = 1)
@MultipartConfig
public class DispatcherServlet extends HttpServlet {
/**
* 收集 Controller - key为请求URL,value为Controller的完成类路径
*/
private static final Map<Object, Object> map = new HashMap<>();
/**
* 加载配置文件
*
* @throws ServletException
*/
@Override
public void init() throws ServletException {
Properties prop = new Properties();
try {
InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("config.properties");
prop.load(input);
prop.forEach(map::put);
} catch (Exception e) {
throw new ServletException(e);
}
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String requestURI = req.getRequestURI();
requestURI = requestURI.replace(this.getServletContext().getContextPath(), "");
String controllerClass = (String) map.get(requestURI);
if (controllerClass != null) {
Object instance = newInstance(controllerClass);
if (instance instanceof Controller) {
try {
Controller controller = (Controller) instance;
controller.execute(req, resp);
} catch (Exception e) {
// 全局异常处理
handleException(resp, e);
}
} else {
throw new ClassCastException(controllerClass
+ " 转换为 cms.project.dom.controller 失败");
}
} else {
req.getServletContext().getNamedDispatcher("default").forward(req, resp);
}
}
/**
* 实例化Controller
*
* @param className
* @return
* @throws ServletException
*/
private Object newInstance(String className)
throws ServletException {
try {
return Class.forName(className).getConstructor().newInstance();
} catch (Exception e) {
throw new ServletException(className + ":实例化失败", e);
}
}
/**
* 全局异常处理
*
* @param resp
* @param e
* @throws IOException
*/
private void handleException(HttpServletResponse resp, Exception e)
throws IOException {
ResponseData responseData = new ResponseData();
responseData.setCode(500);
responseData.setMsg(e.getMessage());
print(resp, responseData);
}
/**
* 响应消息到客户端浏览器
*
* @param resp
* @param responseData
* @throws IOException
*/
private void print(HttpServletResponse resp, ResponseData responseData)
throws IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.print(new GsonBuilder()
.setDateFormat("yyyy-MM-dd hh:mm:ss.SSS")
.create()
.toJson(responseData));
out.flush();
out.close();
}
}
五、封装一个上传的公共类
package cms.project.dom.util;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/***
* @Date(时间)2023-05-17
* @Author 半杯可可
*
*
* 文件上传公共类
*/
public class FileUploadUtil {
/**
* 上传文件最大容量
*/
private long maxSize;
/**
* 设置允许上传文件的类型
*/
private List<String> allowFileExt = new ArrayList<String>();
/**
* <p>
* 设置默认容量和默认允许上传的文件
* </p>
* <p>
* 默认允许上传1MB的文件
* </p>
* <p>
* 默认允许上传的文件类型有:doc、docx、xls、xlsx、pdf、jpg、jpeg、png、gif、rar、zip
* </p>
*/
public FileUploadUtil() {
// 默认允许上传1MB的文件
this.maxSize = 1 * 1024 * 1024;
this.setAllowFileExt("doc,docx,xls,xlsx,pdf,jpg,jpeg,png,gif,rar,zip");
}
/**
* 指定最大容量和允许上传文件
*
* @param maxSize 最大容量
* @param allowFileExt 允许上传文件扩展名,逗号分隔
*/
public FileUploadUtil(long maxSize, String allowFileExt) {
this.maxSize = maxSize;
this.setAllowFileExt(allowFileExt);
}
public long getMaxSize() {
return maxSize;
}
/**
* 设置文件最大容量,默认单位为字节
*
* @param maxSize
*/
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
}
public List<String> getAllowFileExt() {
return allowFileExt;
}
/**
* 设置允许上传文件类型。支持多个,使用英文逗号分隔
*
* @param ext
*/
public void setAllowFileExt(String ext) {
if (ext != null && !"".equals(ext)) {
this.allowFileExt.clear();
}
String[] str = ext.split(",");
for (String s : str) {
this.allowFileExt.add(s);
}
}
/**
* 获取上传原文件名
*
* @param header
* @return
*/
private String getFilename(String header) {
String filename = "";
int beginIndex = header.indexOf("filename=\"") + 10;
int endIndex = header.lastIndexOf("\"");
filename = header.substring(beginIndex, endIndex);
return filename;
}
/**
* 创建UUID字符串
* <p>
* 使用这个字符串作为上传文件的名称,以防止上传文件被替换
*
* @return
*/
private String createUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 获取上传文件扩展名
*
* @param filename 文件名称
* @return 文件后缀(扩展名)
*/
private String getFileExt(String filename) {
String value = "";
if (filename == null || filename.lastIndexOf('.') != -1 && filename.lastIndexOf('.') == filename.length() - 1) {
return "";
}
int beginIndex = filename.lastIndexOf('.') + 1;
int endIndex = filename.length();
value = filename.substring(beginIndex, endIndex);
return value;
}
/**
* 上传文件,文件名为UUID
*
* @param part
* @param path
* @return 返回上传文件名
*/
public String upload(Part part, String path) {
// 获取头信息
String header = part.getHeader("Content-Disposition");
// 获取上传文件的原文件名
String filename = this.getFilename(header);
// 获取上传文件的后缀
String ext = this.getFileExt(filename);
// 重新命名上传文件的名称,以防止上传文件被替换
String newFilename = createUUID() + "." + ext;
// 调用重载文件,实现文件上传,返回上传成功的文件名称
return upload(part, path, newFilename);
}
/**
* 上传文件
*
* @param part
* @param path
* @param flag flag为true,则文件为名UUID,flag为false,则文件名为原文件名
* @return 返回上传文件名
*/
public String upload(Part part, String path, boolean flag) {
String header = part.getHeader("Content-Disposition");
String filename = this.getFilename(header);
String ext = this.getFileExt(filename);
String newFilename = createUUID() + "." + ext;
if (!flag) {
return upload(part, path, newFilename);
}
return upload(part, path, filename);
}
/**
* 上传文件,文件名由用户指定
*
* @param part 上传对象
* @param path 上传路径
* @param file 上传文件名称
* @return
*/
public String upload(Part part, String path, String file) {
// 判断是否允许上传文件容量大小
if (part.getSize() > this.getMaxSize()) {
throw new RuntimeException("上传文件容量溢出,只能上传" + this.getMaxSize() / 1024 * 1024 + "字节文件");
}
// 获取文件后缀
String ext = this.getFileExt(file);
// 判断是否允许上传文件类型
if (!this.getAllowFileExt().contains(ext)) {
throw new RuntimeException("上传失败,只能上传文件的类型有:" + this.getAllowFileExt().toString());
}
// 创建上传目录
File uploadPath = new File(path);
if (!uploadPath.exists()) {
uploadPath.mkdirs();
}
// 获取上传文件路径
String uploadFile = path + File.separator + file;
try {
part.write(uploadFile);
} catch (IOException e) {
e.printStackTrace();
return null;
}
return file;
}
}
六、servlet获取上传图片
package cms.project.dom.controller.WJ;
import cms.project.dom.servlet.BaseController;
import cms.project.dom.util.FileUploadUtil;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
/***
* @Date(时间)2023-05-17
* @Author 半杯可可
* * 上传图片
*/
public class UploadProductImageController extends BaseController {
/**
* 默认图片:compusSLogo.png
*/
private static final String DEFAULT_IMAGE = "compusSLogo.png";
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.当前上传的图片
Part part = req.getPart("attach");
// 2.之前的图片
String lastImage = req.getParameter("lastImage");
// 获取图片上传的物理路径
String path = req.getServletContext().getRealPath("../image");
// 3.删除图片
if (lastImage != null && !"".equals(lastImage)) {
File f = new File(path + File.separator + lastImage);
if (f.exists() && !DEFAULT_IMAGE.equals(lastImage)) {
f.delete();
}
}
// 4.使用上传工具类来实现文件的上传
FileUploadUtil fuu = new FileUploadUtil();
// 设置允许上传文件的大小和类型 - 1MB
fuu.setMaxSize(1 * 1024 * 1024);
fuu.setAllowFileExt("jpg,png,jpeg");
String filename = fuu.upload(part, path);
// 5.响应
print(resp, successJson(200, "success", filename));
}
}
七、删除无效图片
package cms.project.dom.controller.WJ;
import cms.project.dom.servlet.BaseController;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
/***
* @Date(时间)2023-05-17
* @Author 半杯可可
*
* 删除无效图片
*/
public class DeleteProductImageController extends BaseController {
// 默认图片
private static final String DEFAULT_IMAGE = "compusSLogo.png" ;
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.获取无效的图片名称
String deleteImage = req.getParameter("update_last_image");
// 2.获取图片上传的物理路径
String path = req.getServletContext().getRealPath("../image");
// 3.删除图片
if (deleteImage != null && !"".equals(deleteImage)) {
File f = new File(path + File.separator + deleteImage);
if (f.exists() && !DEFAULT_IMAGE.equals(deleteImage)) {
f.delete();
}
}
// 4.响应
print(resp, successJson(200, "success", ""));
}
}
八、JavaScript实现相关功能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo</title>
<!-- 请勿在项目正式环境中引用该 layui.css 地址 -->
<link href="//unpkg.com/layui@2.8.3/dist/css/layui.css" rel="stylesheet">
</head>
<body>
<div class = "div_teachers display_None" id = "div_teacher" >
<div class="layui-form" lay-filter="filter-test-layer" style="margin: 16px;margin-top: 40px;">
<div class="demo-login-container">
<div class="layui-form-item">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
</div>
<div style="border-radius: 5px;border: 2px solid cadetblue;width: 210px;height: 210px;text-align: center; padding: 8px;margin-top:60px;margin-left: 50px;" >
<img id ="pic" src="image/compusSLogo.png" class="cursor" title="资料上传" style="width: 200px;height:200px; border-radius: 5px;border:2px solid cadetblue;">
</div>
</div>
</div>
<button id = "button_pic" style="width: 50px; height:35px;margin-left: 40px;cursor: pointer">浏览</button>
<button style="width: 70px; height:35px;margin-left: 40px;cursor: pointer" onclick="deleteProductImage()">取消上传</button>
</div>
</div>
<!-- 用于记录上传图片的名称,用于存储在数据库中 默认:compusSLogo.png -->
<input type="text" id="update_last_image" value="compusSLogo.png">
</div>
<!-- 请勿在项目正式环境中引用该 layui.js 地址 -->
<script src="//unpkg.com/layui@2.8.3/dist/layui.js"></script>
<script>
// 使用 layui 相关的模块
layui.use(['jquery', 'table', 'layer', 'form','upload'], function () {
// 获取 LayUI 各模块的实例对象
let $ = layui.jquery;
let table = layui.table;
let layer = layui.layer;
let form = layui.form;
let upload = layui.upload;
// 上传图片
let uploadInst = upload.render({
// 绑定浏览文件元素
elem: '#button_pic',
// 实现上传功能的服务器端程序
url: 'mainPage/wj/head',
data: {
// 动态赋值
lastImage: function () {
return $("#update_last_image").val();
}
},
// 设置允许上传的文件类型
accept: 'file',
// 设置允许上传的文件后缀
exts: 'jpg|png|jpeg',
// 设计允许上传文件的大小,单位:KB
size: 10 * 1024,
// 绑定上传控件的字段名,便于服务器获取上传文件
field: "attach",
// 设置不自动上传
auto: true,
// 上传成功的回调
done: function (res) {
// res参数:服务器响应回来的数据,可以封装为responseData对象
// 上传成功后,设置文件名到隐藏域中
if (res.code == 200) {
$("#update_last_image").val(res.data);
return;
}
},
// 上传失败的回调
error: function () {
layer.msg('图片上传失败~~', {icon: 5});
},
// 选择文件后的回调
choose: function (obj) {
obj.preview(function (index, file, result) {
layer.msg('上传成功', {icon: 6});
// 显示图片
$("#pic").prop("src", result);
});
}
});
});
// 删除无效的上传图片
function deleteProductImage() {
// 加载 LayUI 提供的相关模块
layui.use(['layer', 'jquery'], function () {
// 得到模块实例对象
var layer = layui.layer;
var $ = layui.jquery;
$("#pic").prop("src", 'image/compusSLogo.png');
// 发起异步请求,实现图片删除 - 排除默认图片
$.ajax({
url: 'mainPage/wj/delete_product_image',
method: 'post',
data: {'update_last_image': $('#update_last_image').val()},
success: function (res) {
if (res.code == 200) {
layer.msg('成功取消', {icon: 6});
$('#update_last_image').val('compusSLogo.png');
}
}
});
});
}
</script>
</body>
</html>
我这是一个Maven项目,核心控制器需要添加一个名为‘config.properties’文件,必须是这个名
servlet服务器地址名都在这个文件里面配置