本篇文章重点分享一下怎么通过easyui的filebox实现文件上传的功能,从前端代码到后端接口都会展示给大家。
1、form表单同步上传
传统的文件上传会把<input type="file" />放到一个<form></form>里,设置form表单的提交方式为post,而且数据传输格式为multipart/form-data
<form method="post" action="/upload" enctype="multipart/form-data">
请选择文件:<input type="file" name="file" />
<input type="submit" value="提交" />
</form>
2、异步文件上传
以上是表单的同步提交,如果要实现异步文件上传的话,又该怎么做呢?
首先,说一下异步文件上传的基本思路:
文件上传框可以不放在<form>里,而是在<form>标签里面设置一个隐藏域,保存我们文件上传之后后端返回来的url,同时可以通过url回显图片。
本篇文章中,文件上传输入框放在了form表单里,方便通过easyui表单的validate方法验证必填项。
接下来开始步入正题,贴上前端页面的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/themes/icon.css"/>
<link rel="stylesheet" href="/css/themes/default/easyui.css" />
<title>法宝管理>>法宝类型列表</title>
<script src="/js/public/jquery.min.js"></script>
<script src="/js/easyui/jquery.easyui.min.js"></script>
<script src="/js/easyui/easyui-lang-zh_CN.js"></script>
<script src="/js/public/util.js"></script>
<script src="/js/public/public.js"></script>
<script src="/js/fabao/fabao_category_list.js"></script>
</head>
<body>
<form id="search_form">
<table style="border-spacing:5px;">
<tr>
<td><input id="_type" /></td>
<td><input id="_name" /></td>
<td><a id="search">搜索</a></td>
<td><a id="clear">清空</a></td>
</tr>
</table>
</form>
<!-- 法宝类型对话框 -->
<div id="fabao_category_dialog" style="display:none;">
<form id="fabao_category_form">
<input type="hidden" id="id" name="id" />
<table style="border-spacing:5px;">
<tr>
<td>法宝名称</td>
<td><input id="name" name="name" /></td>
<td>法宝类型</td>
<td><input id="type" name="type" /></td>
</tr>
<tr>
<td>法宝信息</td>
<td colspan="3"><input id="note" name="note" /></td>
</tr>
</table>
</form>
</div>
<!-- 修改法宝图片对话框 -->
<div id="upload_dialog" style="display:none;">
<form id="upload_form">
<input type="hidden" id="categoryId" name="id" />
<input type="hidden" id="image" name="image" />
<table style="border-spacing:5px;">
<tr>
<td>上传图片</td>
<td><input id="upload" /></td>
</tr>
<tr>
<td>图片预览</td>
<td><img id="img" height="80" /></td>
</tr>
</table>
</form>
</div>
<table id="fabao_category_list"></table>
</body>
</html>
以上是一个完整页面的HTML代码,我们只需要关注以下代码片段,其中设置了一个<input type="hidden" />用于保存文件上传的回显图片URL,当我们提交表单时,会把这个url一起提交到后台,这时候只需要完成通过ID修改图片的操作。
<div id="upload_dialog" style="display:none;">
<form id="upload_form">
<input type="hidden" id="categoryId" name="id" />
<input type="hidden" id="image" name="image" />
<table style="border-spacing:5px;">
<tr>
<td>上传图片</td>
<td><input id="upload" /></td>
</tr>
<tr>
<td>图片预览</td>
<td><img id="img" height="80" /></td>
</tr>
</table>
</form>
</div>
页面的js代码如下:(注意:这里的datagrid的ajax请求方式默认是get,博主修改了easyui.min.js,并把默认方式改成了post)
let requestUrl;
let types = ["主动法宝", "被动法宝"];
function addHandler() {
requestUrl = "/fabao_category/insert";
$("#fabao_category_dialog").dialog("open");
}
function editHandler() {
let rowData = $("#fabao_category_list").datagrid("getSelected");
if (rowData) {
requestUrl = "/fabao_category/updateById";
$("#id").val(rowData.id);
$("#name").textbox("setValue", rowData.name);
$("#type").combobox("setValue", rowData.type);
$("#note").textbox("setValue", rowData.note);
$("#fabao_category_dialog").dialog("open");
} else {
alertMsg("请选择要修改的记录!", "warning");
}
}
function imageHandler() {
let rowData = $("#fabao_category_list").datagrid("getSelected");
if (rowData) {
requestUrl = "/fabao_category/updateById";
$("#categoryId").val(rowData.id);
$("#image").val(rowData.image);
$("#img").attr("src", rowData.image);
$("#upload_dialog").dialog("open");
} else {
alertMsg("请选择要修改的记录!", "warning");
}
}
$(document).ready(function() {
$("#_type").combobox({
width: 150,
prompt: "法宝类型",
panelHeight: "auto",
data: getJsonData(types)
});
$("#_name").textbox({
prompt: "请输入法宝名称"
});
// 搜索按钮
$("#search").linkbutton({
iconCls: "icon-search"
}).click(function() {
let type = $("#_type").combobox("getValue");
let name = $("#_name").textbox("getValue");
$("#fabao_category_list").datagrid("load", {
type: type,
name: name
});
});
$("#clear").linkbutton({
iconCls: "icon-delete"
}).click(function() {
$("#search_form").form("clear");
});
$("#name").textbox({
width: 120,
required: true
});
$("#type").combobox({
width: 120,
required: true,
panelHeight: "auto",
data: getJsonData(types)
});
$("#note").textbox({
width: 314,
height: 80,
required: true,
multiline: true
});
$("#fabao_category_dialog").dialog({
title: "法宝信息",
modal: true,
closed: true,
closable: false,
draggable: false,
buttons: [{
iconCls: "icon-save",
text: "保存",
handler: function() {
let selector = "#fabao_category_form";
checkForm(selector, function () {
let data = $(selector).serialize();
post(requestUrl, data, function(response) {
showMsg(response.message);
$(selector).form("clear");
$("#fabao_category_dialog").dialog("close");
$("#fabao_category_list").datagrid("reload");
}, error);
});
}
}, {
iconCls: "icon-cancel",
text: "取消",
handler: function() {
$("#fabao_category_dialog").dialog("close");
$("#fabao_category_form").form("clear");
}
}]
});
// 文件上传框
$("#upload").filebox({
buttonText: "选择文件",
width: 200,
required: true,
onChange: function() {
fileUpload(this, "/fabao_category/upload");
}
});
// 上传图片对话框
$("#upload_dialog").dialog({
title: "法宝图片",
modal: true,
closed: true,
closable: false,
draggable: false,
buttons: [{
iconCls: "icon-save",
text: "保存",
handler: function() {
let selector = "#upload_form";
checkForm(selector, function () {
let data = $(selector).serialize();
post(requestUrl, data, function(response) {
showMsg(response.message);
resetValue("#upload");
$(selector).form("clear");
$("#upload_dialog").dialog("close");
$("#fabao_category_list").datagrid("reload");
}, error);
});
}
}, {
iconCls: "icon-cancel",
text: "取消",
handler: function() {
resetValue("#upload");
$("#upload_form").form("clear");
$("#upload_dialog").dialog("close");
}
}]
});
// 法宝类型数据列表
$("#fabao_category_list").datagrid({
url: "/fabao_category/selectByPage",
striped: true,
fitColumns: true,
singleSelect: true,
height: table_height,
pagination: true,
pageList: pageList,
pageSize: pageList[0],
loadFilter: function(result){
if (result.code === 200){
return result.data;
} else {
return null;
}
},
toolbar: [{
iconCls: "icon-add",
text: "添加",
handler: function() {
addHandler()
}
}, "-", {
iconCls: "icon-edit",
text: "修改",
handler: function() {
editHandler();
}
}, "-", {
iconCls: "icon-image",
text: "图片",
handler: function() {
imageHandler();
}
}],
columns: [[
{field: "id", title: "编号", align: "center"},
{field: "name", title: "法宝名称", align: "center", width: 100},
{field: "type", title: "类型", align: "center", width: 100,
formatter: function(value) {
return "<div>" + types[value] + "</div>";
}
},
{field: "image", title: "图片", align: "center", width: 40
, formatter: function(value) {
return "<img height='" + size + "' src='" + value + "' />";
}
},
{field: "note", title: "法宝信息", align: "center", width: 400,
formatter: function(value) {
return "<div class='ell'>" + value + "</div>";
}
}
]]
});
});
重点看以下代码片段
let requestUrl;
function imageHandler() {
let rowData = $("#fabao_category_list").datagrid("getSelected");
if (rowData) {
requestUrl = "/fabao_category/updateById";
$("#categoryId").val(rowData.id);
$("#image").val(rowData.image);
$("#img").attr("src", rowData.image);
$("#upload_dialog").dialog("open");
} else {
alertMsg("请选择要修改的记录!", "warning");
}
}
$(document).ready(function() {
$("#upload").filebox({
buttonText: "选择文件",
width: 200,
required: true,
onChange: function() {
fileUpload(this, "/fabao_category/upload");
}
});
$("#upload_dialog").dialog({
title: "法宝图片",
modal: true,
closed: true,
closable: false,
draggable: false,
buttons: [{
iconCls: "icon-save",
text: "保存",
handler: function() {
let selector = "#upload_form";
checkForm(selector, function () {
let data = $(selector).serialize();
post(requestUrl, data, function(response) {
showMsg(response.message);
resetValue("#upload");
$(selector).form("clear");
$("#upload_dialog").dialog("close");
$("#fabao_category_list").datagrid("reload");
}, error);
});
}
}, {
iconCls: "icon-cancel",
text: "取消",
handler: function() {
$("#upload_form").form("clear");
$("#upload_dialog").dialog("close");
}
}]
});
});
当我们选中某行数据时,点击【图片】按钮,就会打开我们的文件上传的对话框,同时如果这行记录本来的图片不为空,也会显示出来,并且设置隐藏域<input id="image" />的value为该记录的image值。
效果图片大概是这样
当我们点击上传文件后面的选择框并选择图片上传时,会提交post请求到接口"/fabao_category/upload",完成文件的上传,上传成功后会返回文件的相对路径,然后重新设置图片预览后面的的图片的src属性为返回的URL。
当我们点击保存按钮时,会通过ajax的post请求的方式提交表单数据到我们的"/fabao_category/updateById"接口,就是修改法宝类型信息的接口。数据修改成功之后会刷新表格数据。
$("#fabao_category_list").datagrid("reload");
js文件里的多个方法来自于util.js
let wkf = "该功能暂未开放,敬请期待~";
let base = "http://localhost:9091/api/mhxysy";
base = "";
/**
* 封装的ajax get请求
* @param url 请求url
* @param params 请求参数
* @param success 成功回调函数
* @param error 失败回调函数
* @param async 是否异步
*/
function get(url, params, success, error, async = true) {
$.ajax({
type: "GET",
url: base + url,
data: params,
cache: false,
async: async,
dataType: "json",
processData: true,
success: success,
error: error
});
}
/**
* 封装的ajax post请求
* @param url 请求url
* @param params 请求参数
* @param success 成功回调函数
* @param error 失败回调函数
* @param async 是否异步
*/
function post(url, params, success, error, async = true) {
$.ajax({
type: "POST",
url: base + url,
data: params,
async: async,
cache: false,
dataType: "json",
processData: true,
success: success,
error: error
});
}
/**
* Ajax POST请求
* @param url 请求路径
* @param data 请求参数
* @param success 成功回调
* @param error 失败回调
*/
function ajaxPost(url, data, success, error) {
$.ajax({
url: base + url,
data: data,
cache: false,
async: true,
type: "POST",
dataType: "json",
processData: false,
contentType: false,
success: success,
error: error
});
}
let error = (res) => {
console.log(res);
if (res && res.responseJSON) {
let response = res.responseJSON;
if (res.status && res.status === 404) {
let message;
if(response.path) {
message = "路径" + response.path + "不存在。";
} else {
message = response.message;
}
alertMsg(message, "error");
} else {
alertMsg(response.message, "error");
}
}
}
/**
* 右下角弹出消息提示
* @param message 提示消息
* @param type 消息类型
*/
function showMsg(message, type = "slide") {
$.messager.show({
title: "消息",
msg: message,
timeout: 3000,
showType: type
});
}
/*
* 弹出提示
* @param message 提示消息
* @param type 提示类型:warning/error/info/question
*/
function alertMsg(message, type = "info") {
$.messager.alert("提示", message, type);
}
/**
* 重置文件上传组件的值
* @param selector 组件的选择器
*/
function resetValue(selector) {
$(selector).filebox("initValue", null);
}
/**
* 功能未开放
*/
function unopen() {
alertMsg(wkf);
}
function unselected() {
alertMsg("请选择一条记录!", "warning");
}
function fileUpload(_obj, url) {
let file = $(_obj).context.ownerDocument.activeElement.files[0];
let form = new FormData();
form.append("file", file);
ajaxPost(url, form, function (result) {
let image = result.data;
$("#image").val(image);
$("#img").attr("src", image);
}, error);
}
/**
* 验证表单
* @param selector 选择器
* @param func 表单验证通过后执行的操作
*/
function checkForm(selector, func) {
let $form = $(selector);
let bool = $form.form("validate");
if (bool) {
func();
} else {
alertMsg("请填写正确的表单项", "warning");
}
}
/**
* 根据数组获取json格式的数据
* @param arr
*/
function getJsonData(arr) {
let jsonData = [];
for (let i = 0; i < arr.length; i++) {
let elem = {"value": i + "", "text": arr[i]};
jsonData.push(elem);
}
return jsonData;
}
/**
* 初始化easyui数据列表datagrid
* @param selector 选择器
* @param url 加载数据的URL
* @param toolbar 头部工具栏
* @param columns 表格的列
* @param height 表格高度
* @param pageList 分页参数
* @param rownumbers 是否显示行号
*/
function asDatalist(selector, url, toolbar, columns, height = 432, pageList = [10, 20, 50, 100], rownumbers = false) {
$(selector).datagrid({
url: url,
striped: true,
height: height,
fitColumns: true,
singleSelect: true,
rownumbers: rownumbers,
pagination: true,
pageList: pageList,
pageSize: pageList[0],
loadFilter: function(result){
if (result.code === 200){
return result.data;
} else {
return null;
}
},
toolbar: toolbar,
columns: columns
});
}
接下来看一下后端的接口怎么写的:
FabaoCategoryController.java
package cn.edu.sgu.www.mhxysy.controller.fabao;
import cn.edu.sgu.www.mhxysy.restful.JsonResult;
import cn.edu.sgu.www.mhxysy.restful.PageResult;
import cn.edu.sgu.www.mhxysy.entity.fabao.FabaoCategory;
import cn.edu.sgu.www.mhxysy.pager.fabao.FabaoCategoryPager;
import cn.edu.sgu.www.mhxysy.service.fabao.FabaoCategoryService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@RestController
@Api(tags = "法宝类型控制器类")
@RequestMapping(path = "/fabao_category", produces="application/json; charset=utf-8")
public class FabaoCategoryController {
private final FabaoCategoryService service;
@Autowired
public FabaoCategoryController(FabaoCategoryService service) {
this.service = service;
}
@ApiOperation("添加法宝类型")
@RequestMapping(value = "/insert", method = RequestMethod.POST)
public JsonResult<Void> insert(FabaoCategory category) {
service.insert(category);
return JsonResult.success("添加成功");
}
@ApiOperation("通过id修改法宝类型信息")
@RequestMapping(value = "/updateById", method = RequestMethod.POST)
public JsonResult<Void> updateById(FabaoCategory category) {
service.updateById(category);
return JsonResult.success("修改成功");
}
@ApiOperation("查询全部法宝类型")
@RequestMapping(value = "/selectAll", method = RequestMethod.GET)
public List<FabaoCategory> selectAll() {
return service.selectAll();
}
@ApiOperation("通过id查询法宝类型信息")
@RequestMapping(value = "/selectById", method = RequestMethod.GET)
public FabaoCategory selectById(@RequestParam Integer id) {
return service.selectById(id);
}
@ApiOperation("分页查询法宝类型列表")
@RequestMapping(value = "/selectByPage", method = RequestMethod.POST)
public JsonResult<PageResult<FabaoCategory>> selectByPage(FabaoCategoryPager pager) {
Page<FabaoCategory> result = service.selectByPage(pager);
return JsonResult.restPage(result);
}
@ApiOperation("上传图片")
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public JsonResult<String> upload(MultipartFile file) throws IOException {
String url = service.upload(file);
return JsonResult.success(null, url);
}
}
FabaoCategoryServiceImpl.java
package cn.edu.sgu.www.mhxysy.service.fabao.impl;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import cn.edu.sgu.www.mhxysy.base.Pager;
import cn.edu.sgu.www.mhxysy.consts.DirectoryConsts;
import cn.edu.sgu.www.mhxysy.entity.fabao.FabaoCategory;
import cn.edu.sgu.www.mhxysy.mapper.fabao.FabaoCategoryMapper;
import cn.edu.sgu.www.mhxysy.pager.fabao.FabaoCategoryPager;
import cn.edu.sgu.www.mhxysy.service.fabao.FabaoCategoryService;
import cn.edu.sgu.www.mhxysy.util.UploadUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
* @author heyunlin
* @version 1.0
*/
@Service
public class FabaoCategoryServiceImpl implements FabaoCategoryService {
private final UploadUtils uploadUtils;
private final FabaoCategoryMapper mapper;
@Autowired
public FabaoCategoryServiceImpl(UploadUtils uploadUtils, FabaoCategoryMapper mapper) {
this.uploadUtils = uploadUtils;
this.mapper = mapper;
}
@Override
public void insert(FabaoCategory category) {
mapper.insert(category);
}
@Override
public void updateById(FabaoCategory category) {
mapper.updateById(category);
}
@Override
public List<FabaoCategory> selectAll() {
return mapper.selectList(null);
}
@Override
public FabaoCategory selectById(Integer id) {
return mapper.selectById(id);
}
@Override
public Page<FabaoCategory> selectByPage(FabaoCategoryPager pager) {
QueryWrapper<FabaoCategory> wrapper = new QueryWrapper<>();
Page<FabaoCategory> page = Pager.ofPage(pager);
wrapper.eq(
pager.getType() != null,
"type", pager.getType()
);
wrapper.like(
StringUtils.isNotEmpty(pager.getName()),
"name", pager.getName()
);
return mapper.selectPage(page, wrapper);
}
@Override
public String upload(MultipartFile file) throws IOException {
String directory = DirectoryConsts.DIRECTORY_FABAO;
return uploadUtils.upload(file, directory);
}
}
DirectoryConsts.java
DirectoryConsts就是一个存放常量的接口,保存项目用到的文件上传的相对路径
package cn.edu.sgu.www.mhxysy.consts;
/**
* 常量工具类
* 定义了项目用到的文件上传路径相对根路径root的文件夹
*/
public interface DirectoryConsts {
/**
* 角色图片上传文件夹
*/
String DIRECTORY_ROLE = "/role/head";
/**
* 烹饪图片上传文件夹
*/
String DIRECTORY_CUISINE = "/cuisine";
/**
* 药品图片上传文件夹
*/
String DIRECTORY_MEDICINE = "/medicine";
/**
* 角色日常记录图片上传文件夹
*/
String DIRECTORY_DAILY_RECORD = "/daily_record";
/**
* 角色时装图片上传文件夹
*/
String DIRECTORY_ROLE_SHIZHUANG = "/role_shizhuang";
/**
* 特技图片上传文件夹
*/
String DIRECTORY_TETJ = "/teji";
/**
* 法宝图片上传文件夹
*/
String DIRECTORY_FABAO = "/fabao";
/**
* 坐骑图片上传文件夹
*/
String DIRECTORY_ZUOQI = "/zuoqi";
/**
* 门派图片上传文件夹
*/
String DIRECTORY_SCHOOL = "/school";
/**
* 门派法宝图片上传文件夹
*/
String DIRECTORY_SCHOOL_FABAO = "/school_fabao";
/**
* 器灵图片上传文件夹
*/
String DIRECTORY_QILING = "/qiling";
/**
* 宠物图片上传文件夹
*/
String DIRECTORY_CHONGWU = "/chongwu";
/**
* 助战图片上传文件夹
*/
String DIRECTORY_PARTNER = "/partner";
/**
* 助战图片上传文件夹
*/
String DIRECTORY_PARTNER_SKILL = "/partner_skill";
/**
* 装备图片上传文件夹
*/
String DIRECTORY_EQUIPMENT = "/equipment";
/**
* 修炼技能图片上传文件夹
*/
String DIRECTORY_XIULIAN = "/xiulian";
/**
* 变身卡图片上传文件夹
*/
String DIRECTORY_BIANSHENKA = "/bianshenka";
/**
* 坐骑技能图片上传文件夹
*/
String DIRECTORY_ZUOQI_SKILL = "/zuoqi_skill";
/**
* 门派技能图片上传文件夹
*/
String DIRECTORY_SCHOOL_SKILL = "/school_skill";
/**
* 宠物技能图片上传文件夹
*/
String DIRECTORY_CHONGWU_SKILL = "/chongwu_skill";
/**
* 宠物内丹图片上传文件夹
*/
String DIRECTORY_CHONGWU_NEIDAN = "/chongwu_neidan";
/**
* 宠物套装技能图片上传文件夹
*/
String DIRECTORY_CHONGWU_TAOZHUANG = "/chongwu_taozhuang";
/**
* 宠物专属内丹图片上传文件夹
*/
String DIRECTORY_ZHUANSHUNEIDAN = "/zhuanshu_neidan";
/**
* 器灵套装图片上传文件夹
*/
String DIRECTORY_QILING_TAOZHUANG = "/qiling_taozhuang";
/**
* 宠物装备图片上传文件夹
*/
String DIRECTORY_CHONGWU_EQUIPMENT = "/chongwu_equipment";
/**
* 器灵套装图片上传文件夹
*/
String DIRECTORY_QILING_TAOZHUANG_IMAGE = "/qiling_taozhuang_image";
/**
* 星印图片上传文件夹
*/
String DIRECTORY_XINGYIN = "/xingyin";
/**
* 星印图片上传文件夹
*/
String DIRECTORY_XINGYIN_SKILL = "/xingyin_skill";
/**
* 星印特效图片上传文件夹
*/
String DIRECTORY_XINGYIN_TEXIAO = "/xingyin_texiao";
/**
* 装备制造书图片上传文件夹
*/
String DIRECTORY_FORGE_BOOK = "/forge_book";
}
UploadUtils.java
UploadUtils是文件上传工具类,定义为组件,因为要读取配置文件
package cn.edu.sgu.www.mhxysy.util;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/**
* 文件上传工具类
* @author heyunlin
* @version 1.0
*/
@Component
public class UploadUtils {
/**
* 文件上传根路径
*/
@Value("${uploads.path}")
private String root;
public String getRoot() {
return root;
}
/**
* 图片上传
* @param file MultipartFile对象
* @param directory 文件上传目录
* @return JsonResult<String>
*/
public String upload(MultipartFile file, String directory) throws IOException {
boolean result = check(file);
if (result) {
// 获取文件名
String fileName = StringUtils.getFileName(file);
// 创建目标对象
File targetFile = new File(root + directory, fileName);
// 保存文件
file.transferTo(targetFile);
return directory + "/" + fileName;
}
return null;
}
/**
* 检查文件格式
* @param file MultipartFile
*/
private boolean check(MultipartFile file) {
if (file == null) {
throw new GlobalException(ResponseCode.BAD_REQUEST, "您未上传任何图片!");
}
String filename = file.getOriginalFilename();
if (StringUtils.isNotEmpty(filename)) {
String fileType = StringUtils.getFileType(filename).toLowerCase();
// 图片文件名后缀
String picPrefix = ".webp,.jpeg,.jpg,.png";
if (!picPrefix.contains(fileType)) {
throw new GlobalException(ResponseCode.BAD_REQUEST, "只允许上传格式为" + picPrefix + "的图片");
}
return true;
} else {
throw new GlobalException(ResponseCode.BAD_REQUEST, "获取上传的文件名失败~");
}
}
}
StringUtils.java
这是字符串工具类,封装常用的字符串相关方法
package cn.edu.sgu.www.mhxysy.util;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* String工具类
* @author heyunlin
* @version 1.0
*/
public class StringUtils {
/**
* 判断字符串是否为null或""
* 字符串为""或null返回true,否则返回false
* @param str 要判断的字符串
* @return boolean
*/
public static boolean isEmpty(String str) {
return str == null || str.isEmpty() || isBlank(str);
}
/**
* 判断字符串是否为""或null
* 字符串为""或null返回false,否则返回true
* @param str 要判断的字符串
* @return boolean
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* 判断字符串是否为空白字符
* 字符串为空白字符返回true,否则返回false
* @param str 要判断的字符串
* @return boolean
*/
public static boolean isBlank(String str) {
return str.trim().length() == 0;
}
/**
* 判断字符串是否不是空白字符
* 字符串不是空白字符返回true,否则返回false
* @param str 要判断的字符串
* @return boolean
*/
public static boolean isNotBlank(String str) {
return !isBlank(str);
}
/**
* 判断字符串是否为null或""
* 字符串为""或null返回true,否则返回false
* @param str 要判断的字符串
* @return boolean
*/
public static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
/**
* 检查字符串是否包含空白字符
* 如果不包含空格返回true,否则返回false
* @param str 需要比较的字符串
* @return boolean
*/
public static boolean check(String str) {
// 去除空白字符后字符串的长度
int realLength = str.replaceAll("\\s", "").length();
// 字符串原来的长度
int originalLength = str.length();
return realLength == originalLength;
}
/**
* 根据当前时间生成UUID
* @return String
*/
public static String uuid() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDateTime localDate = LocalDateTime.now();
return localDate.format(formatter);
}
/**
* 通过文件名获取文件类型
* @param fileName 文件名
*/
public static String getFileType(String fileName) {
// 得到文件名中最后一次出现"."的位置
int index = fileName.lastIndexOf('.');
// 文件类型统一转换为小写
return fileName.substring(index).toLowerCase();
}
/**
* 获取文件名
* @param filename String
* @return String 由当前时间生成的新文件名
*/
public static String getFileName(String filename) {
// 返回uuid.文件类型,如:20220618131456.jpg
return uuid() + getFileType(filename);
}
/**
* 获取文件名
* @param file MultipartFile对象
* @return String 由当前时间生成的新文件名
*/
public static String getFileName(MultipartFile file) {
// 得到上传文件的原始文件名
String filename = file.getOriginalFilename();
// 判断文件名是否为空
if (isNullOrEmpty(filename)) {
throw new RuntimeException("获取文件名失败!");
}
// 返回uuid.文件类型,如:20220618131456.jpg
return uuid() + getFileType(filename);
}
/**
* 驼峰命名转下划线命名
* @param str 待转换的字符串
* @return String
*/
public static String toLowerCase(String str) {
// 小写和大写紧挨一起的地方加上分隔符_,然后全部转为小写
str = str.replaceAll("([a-z])([A-Z])", "$1_$2");
return str.toLowerCase();
}
/**
* 下划线命名转驼峰命名
* @param str 待转换的字符串
* @return String
*/
private static String toUpperCase(String str) {
// 将下划线替换为空格
StringBuilder under= new StringBuilder();
str = str.toLowerCase().replace("_", " ");
// 将字符串根据空格分割成数组
String[] array = str.split(" ");
// 将每个单词首字母大写
for (String s : array) {
String letter = s.substring(0, 1).toUpperCase() + s.substring(1);
under.append(letter);
}
return under.toString();
}
}
最后是统一自定义异常GlobalException
package cn.edu.sgu.www.mhxysy.exception;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 自定义异常
* @author heyunlin
* @version 1.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class GlobalException extends RuntimeException {
private ResponseCode responseCode;
public GlobalException(ResponseCode responseCode, String message) {
super(message);
setResponseCode(responseCode);
}
}
配合全局异常处理类,就可以在项目运行过程时发生异常主动捕获,并调用对应的异常处理方法返回响应对象
package cn.edu.sgu.www.mhxysy.exception.handler;
import cn.edu.sgu.www.mhxysy.restful.JsonResult;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
/**
* 全局异常处理类
* @author heyunlin
* @version 1.0
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理GlobalException
* @param e GlobalException
* @return JsonResult<Void>
*/
@ExceptionHandler(GlobalException.class)
public JsonResult<Void> handlerGlobalException(HttpServletResponse response, GlobalException e) {
System.err.println(e.getMessage());
e.printStackTrace();
response.setStatus(e.getResponseCode().getValue());
return JsonResult.error(e.getResponseCode(), e);
}
/**
* 处理BindException
* @param e BindException
* @return JsonResult<Void>
*/
@ExceptionHandler(BindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public JsonResult<Void> handlerBindException(BindException e) {
e.printStackTrace();
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
String defaultMessage = fieldError.getDefaultMessage();
return JsonResult.error(ResponseCode.BAD_REQUEST, defaultMessage);
}
/**
* 处理Exception
* @param e Exception
* @return JsonResult<Void>
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public JsonResult<Void> handlerException(Exception e) {
e.printStackTrace();
return JsonResult.error(ResponseCode.ERROR, e);
}
}
整个项目的结构如下
好了,这篇文章就分享到这里了,如果文章对你有所帮助,不要忘了点赞+收藏哦~