前端技巧
HTML
form表单
input的type常用类型
- text属性
input标签type默认属性为text
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<input type="text" size="10" value="哈哈">
<input type="text" name="fruit" placeholder="水果" list="datalist1">
<datalist id="datalist1">
<option>苹果</option>
<option>香蕉</option>
<option>菠萝</option>
<option>西瓜</option>
</datalist>
<input type="submit" value="提交">
</form>
</body>
</html>
2. textarea标签(文本长宽可调)
<textarea name="ha" rows="10px" cols="20px"></textarea>
3. range和number标签
<input type="range" min="0" max="100" step="20">
<input type="number" min="0" max="200" step="20">
4. checkbox和radio
<input type="checkbox">选择
<input type="radio" name="animal" value="cat" checked>猫
<input type="radio" name="animal" value="dog">狗
5. date
<input type="date" name="date">
6. hidden和submit
<input type="hidden" name="hidden" value="1" >
<input type="submit" value="提交">
- file
<input type="file" required multiple><!--required 必须有内容 所有input都可以指定 multiple可以选多个-->
需添加form表单属性
<form enctype="multipart/form-data">
图片分区响应
<img src="timg.jpg" alt="加载失败" width="128px" height="128px" usemap="#map1">
<map name="map1">
<area shape="circle" coords="63px,56px,45px" href="https://www.baidu.com"></map>
</map>
1、距形:(左上角顶点坐标为(x1,y1),右下角顶点坐标为(x2,y2))
<area shape="rect" coords="x1,y1,x2,y2" href=url>
2、圆形:(圆心坐标为(X1,y1),半径为r)
<area shape="circle" coords="x1,y1,r" href=url>
视频播放
<video src="WeChat_20190507151006.mp4" controls loop>
<source src="WeChat_20190507151006.mp4" type="video/mp4">
<source src="WeChat_20190507151006.ogv" type="video/ogv">
</video>
src: 输入视频的地址
height: 视频高度 只设置高度 宽度会自适应
controls: 视频可选择播放、暂停、调声音、全屏和缩小等
autoplay: 打开自动播放
preload: none 不加载(打开页面就预先加载部分视频)
:metadata 加载第一帧
:auto 加载 默认是加载的
Loop: 视频循环播放
Poster: 视频载入时显示图片(首图)
Muted: 视频静音
source标签
用视频转换器转换视频格式,浏览器不支持视频格式时会去加载source里的格式
把video换成audio,可以音频播放
CSS
样式选择器
类型选择器
所有的a标签都会使用该样式
a{
font-size: 40px;
color: red;
}
类选择器
所有属性有 class="class1" 的标签会有该样式
.class1{
}
id选择器
作用于标注id1的
#id1{
}
:选择器
a:hover{
}
background背景图
body{
background-image: url("timg.jpg");
background-repeat: no-repeat; 不重复出现
background-attachment: local; 显示位置
background-size: cover; 全页面显示 默认为auto
}
text文本样式
text-align: center; 文本居中
letter-spacing: 22px; 字间距
line-height: 10px; 行高
text-indent: 50px; 首行缩进
text-decoration: overline;上划线
text-decoration: underline;下划线
line-through;中划线
text-transform: capitalize; 首字母自动大写
uppercase;全大写
font-family: 宋体; 设置字体
font-style: italic; 斜体
font-weight: bold;加粗
transition过渡
p{
width: 100px;
height: 100px;
background-color: beige;
}
p:hover{
width: 200px;
height: 200px;
background-color: coral;
transition-delay: 100ms; 延迟变化时间
transition-duration: 1s; 渐进
transition-property:background-color,width;过渡只作用在选的属性上 可设置其他的
transition-timing-function: ease; 变化越来越慢 ease-in 越来越快 ease-in-out 中间快 两边慢 默认线性变化
}
animation动画
p{
width: 100px;
height: 100px;
background-color: beige;
}
p:hover{
animation-delay: 200ms;
animation-duration: 1s;
animation-name: donghua;
animation-iteration-count: infinite; 动画次数
animation-direction: alternate; 交替变换(小->大->小) 不带是 小->大 小->大
}
@keyframes donghua {
from{
width: 120px;
height: 120px;
background-color: beige;
}
50%{
width: 50px;
height: 50px;
background-color: blue;
}
to{
width: 200px;
height: 200px;
background-color: coral;
}
}
transform变化
p{
width: 100px;
height: 100px;
background-color: beige;
}
p:hover{
width: 150px;
height: 150px;
transform: rotate(30deg);顺时针转动30度
scale(1.5); 鼠标经过会变成1.5倍
transform-origin: bottom right; 旋转点(锚点)
}
javaScript
数据类型
String: 字符串
Number: 数字
Boolean: 布尔
Null: 空值
undefined:未定义
Object: 对象
特殊数据和查看数据类型
Infinity 无穷 number
NaN 类型 number
null 类型Object
var a;
console.log(typeof a); typeof a可以查看a的类型
类型转换
转String:
var a;
a = String(a);
转Number:
Number(a);
a为非数字字符串时转为NaN
a为true时,转为1,false为0
parseInt()和parseFloat()可以将字符串开头是数字的转为number
转Boolean
Boolean(a);
a为 "",0,null,undefined,NaN时转为false,其余都是true
jQuery
基础
jQuery 插件
1. 插件都需要引来Jquery.js
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
jQuery Validation
1. 导入js
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/localization/messages_zh.min.js"></script>
<!-- 自定义方法 -->
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/additional-methods.min.js"></script>
2. example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/localization/messages_zh.min.js"></script>
<!-- 自定义方法 -->
<script src="https://cdn.bootcss.com/jquery-validate/1.19.1/additional-methods.min.js"></script>
<script>
<form id="inputForm" class="form-horizontal" th:action="@{/user/save}" method="post">
<div class="box-body">
<div class="form-group">
<label for="username3" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-10">
<input name="username" class="form-control required" th:value="${user.getUsername()}" id="username3" placeholder="请输入用户的用户名">
</div>
</div>
<div class="form-group" hidden>
<div class="col-sm-10">
<input name="id" th:value="${user.getId()}">
</div>
</div>
<div class="form-group">
<label for="mobile3" class="col-sm-2 control-label">电话</label>
<div class="col-sm-10">
<input name="mobileNumber" class="form-control required mobile" th:value="${user.getMobileNumber()}" id="mobile3" placeholder="请输入用户的电话">
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">邮箱</label>
<div class="col-sm-10">
<input type="email" name="email" class="form-control required email" th:value="${user.getEmail()}" id="inputEmail3" placeholder="请输入用户的邮箱">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">密码</label>
<div class="col-sm-10">
<input type="password" name="password" class="form-control required" id="inputPassword3" th:value="${user.getPassword()}" placeholder="请输入用户的密码">
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="button" class="btn btn-default" onclick="history.back();">返回</button>
<button type="submit" class="btn btn-info pull-right">提交</button>
</div>
<!-- /.box-footer -->
</form>
validate.js
/**
* 函数对象
* @constructor
*/
var Validate = function () {
var initValidate = function () {
$.validator.addMethod("mobile", function (value, element) {
var length = value.length;
var mobile = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;
return this.optional(element) || (length == 11 && mobile.test(value));
}, "手机号码格式错误");
};
/**
* 表单验证
* @param formId
*/
var ValidateForm = function (formId) {
$("#" + formId).validate({
errorElement: 'span',
errorClass: 'help-block',
errorPlacement: function (error, element) {
element.parent().parent().attr("class", "form-group has-error");
error.insertAfter(element);
}
});
};
return {
initValidate: function () {
initValidate();
},
validateForm: function (formId) {
ValidateForm(formId);
}
}
}();
$(function () {
Validate.initValidate();
});
jQuery iCheck
<link href="https://cdn.bootcss.com/iCheck/1.0.2/skins/all.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/iCheck/1.0.2/icheck.min.js"></script>
1. 使用 <input type="checkbox" class="minimal"> (放入table的 th开头和tr开头)
2. 初始化ICheck,导入js
3. 第一个iCheck控制所有iCheck
delMul.js
var app = function(){
var icheck_master,_icheck,idArr;
/**
* 初始化
*/
var initICheck = function () {
$('input[type="checkbox"].minimal, input[type="radio"].minimal').iCheck({
checkboxClass: 'icheckbox_minimal-blue',
radioClass : 'iradio_minimal-blue'
});
icheck_master = $('input[type="checkbox"].minimal.icheck_master');
_icheck = $('input[type="checkbox"].minimal');
};
var delMul = function (url) {
idArr = new Array();
_icheck.each(function () {
var _id = $(this).attr("id");
if(_id != null && _id != "undefine" && $(this).is(":checked")){
idArr.push(_id);
}
});
if(idArr.length === 0){
$("#modal-default-message").html("至少需要选中一个");
}else{
$("#modal-default-message").html("确定删除吗");
}
$("#modal-default").modal("show");
/*绑定点击事件 绑定前先取消绑定事件*/
$(".modal-footer .btn.btn-primary").unbind("click");
$(".modal-footer .btn.btn-primary").bind("click",function () {
if(idArr.length !== 0){
del();
}
$("#modal-default").modal("hide");
});
function del() {
$.ajax({
url: url,
type: "POST",
data: {"ids": idArr.toString()},
datatype: "JSON",
success: function (data) {
if(data.status === 200){
$("#modal-result-message").html("删除成功");
}else{
$("#modal-result-message").html(data.message);
}
$("#modal-result").modal("show");
}
});
}
};
/**
* 全选
*/
var iCheckAll = function () {
icheck_master.on("ifClicked",function (e) {
//选中为false
if (e.target.checked) {
_icheck.iCheck("uncheck");
}else{
_icheck.iCheck("check");
}
});
};
return {
init: function () {
initICheck();
iCheckAll();
},
getICheck: function () {
return _icheck;
},
delMul: function (url) {
delMul(url);
}
}
}();
$(function () {
app.init();
});
example
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/iCheck/1.0.2/skins/all.css" rel="stylesheet">
</head>
<body>
<button onclick="app.delMul('/del')">批量删除</button>
<table>
<th><input type="checkbox" class="minimal icheck_master"></th>
<tr>
<td><input id="1" type="checkbox" class="minimal"></td>
</tr>
<tr>
<td><input id="2" type="checkbox" class="minimal"></td>
</tr>
<tr>
<td><input id="3" type="checkbox" class="minimal"></td>
</tr>
<tr>
<td><input id="4" type="checkbox" class="minimal"></td>
</tr>
</table>
<!--模块框-->
<div th:replace="~{common/modal::default}"></div>
<div th:replace="~{common/modal::result}"></div>
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.bootcss.com/iCheck/1.0.2/icheck.min.js"></script>
<script src="../static/assets/delMul.js" th:src="@{/assets/delMul.js}"></script>
</body>
</html>
modal.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--模块框-->
<div class="modal fade" id="modal-default" th:fragment="default">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">温馨提示</h4>
</div>
<div class="modal-body">
<p id="modal-default-message"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="modal-confirm">确定</button>
</div>
</div>
</div>
</div>
<!--结果模块框-->
<div class="modal fade" id="modal-result" th:fragment="result">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">温馨提示</h4>
</div>
<div class="modal-body">
<p id="modal-result-message"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
</body>
</html>
jQuery DataTables
DataTables是伪分页,通过jquery实现页面显示分页(数据不要超过5W条)
<link href="https://cdn.bootcss.com/datatables/1.10.19/css/dataTables.bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/datatables/1.10.19/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.bootcss.com/datatables/1.10.19/js/dataTables.bootstrap.min.js"></script>
使用
<table id="example" class="table table-bordered table-striped">
<thead>
<tr>
<th><input type="checkbox" class="minimal icheck_master"></th>
<th>id</th>
<th>电话</th>
<th>密码</th>
<th>昵称</th>
<th>创建时间</th>
<th>修改时间</th>
<th>操作</th>
</tr>
</thead>
</table>
<script>
$(function () {
var columns = [
{
"data": function (row, type, val, meta) {
return '<input id="' + row.id + '" type="checkbox" class="minimal" />';
}
},
{"data": "id"},
{"data": "mobileNumber"},
{"data": "loginPwd"},
{"data": "nickname"},
{"data": "ctime"},
{"data": "mtime"},
{
"data": function (row, type, val, meta) {
var detailUrl = "'/selectOne?id="+row.id+"'";
return '<button class="btn btn-sm btn-default" οnclick="userDetail('+detailUrl+');"><i class="fa fa-search"></i> 查看</button> ' +
'<a href="#" type="button" class="btn btn-sm btn-primary"><i class="fa fa-edit"></i> 编辑</a> ' +
'<a href="#" type="button" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i> 删除</a>'
}
}
];
app.initDataTables("/page", columns);
});
/*查看个人详情*/
function userDetail(url){
$.ajax({
url: url,
type: "get",
dataType: "html",
success: function (data) {
$("#modal-result-message").html(data);
$("#modal-result").modal("show");
}
});
}
</script>
var initDataTables = function (url,columns) {
$("#example").DataTable({
// 是否开启本地分页
"paging": true,
// 是否开启本地排序
"ordering": false,
// 是否显示左下角信息
"info": true,
// 是否允许用户改变表格每页显示的记录数
"lengthChange": false,
// 是否显示处理状态(排序的时候,数据很多耗费时间长的话,也会显示这个)
"processing": true,
// 是否允许 DataTables 开启本地搜索
"searching": false,
// 是否开启服务器模式
"serverSide": true,
// 控制 DataTables 的延迟渲染,可以提高初始化的速度
"deferRender": true,
// 分页按钮显示选项
"pagingType": "full_numbers",
ajax: {
url: url,
type: "get"
},
// 表格重绘的回调函数
"drawCallback": function (settings) {
app.init();
},
"columns": columns,
"language": {
"sProcessing": "处理中...",
"sLengthMenu": "显示 _MENU_ 项结果",
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
}
});
}
jQuery TreeTable
1. 添加样式和js
<link href="https://cdn.bootcss.com/jquery-treetable/3.2.0/css/jquery.treetable.min.css" rel="stylesheet">
<style>
table.treetable tr.collapsed span.indenter a {
background-image: url(data:image/png;base64,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);
}
table.treetable tr.expanded span.indenter a {
background-image: url(data:image/png;base64,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);
}
</style>
<script src="https://cdn.bootcss.com/jquery-treetable/3.2.0/jquery.treetable.min.js"></script>
<script>
$(function () {
//table的id
$("#treeTable").treetable({
column: 1,//第二列
expandable: true,//树为可扩展的
stringExpand:"展开",//国际化
stringCollapse:"收起",//国际化
});
});
</script>
2. table的<tr>标签绑定data-tt-id和data-tt-parent-id属性
<div class="box-body table-responsive">
<table id="treeTable" class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>排序</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="contentCatetory:${list}" th:attr="data-tt-id=${contentCatetory.id},data-tt-parent-id=${contentCatetory.parentId}">
<td th:text="${contentCatetory.id}"></td>
<td th:text="${contentCatetory.name}"></td>
<td th:text="${contentCatetory.sortOrder}"></td>
<td>
<a href="#" type="button" class="btn btn-sm btn-primary"><i class="fa fa-edit"></i> 编辑</a>
<button href="#" type="button" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i> 删除</button>
<a href="#" type="button" class="btn btn-sm btn-default">增加下一级内容</a>
</td>
</tr>
</tbody>
</table>
</div>
3. 返回的list顺序要按显示的顺序
private static void sortList(List<ContentCategory> sourceList,List<ContentCategory> targetList,Integer parentId){
for (ContentCategory sourceContentCategory : sourceList) {
if (sourceContentCategory.getParentId().equals(parentId)) {
targetList.add(sourceContentCategory);
//判断是否有子节点
if (sourceContentCategory.getIsParent().equals(1)) {
sortList(sourceList,targetList,sourceContentCategory.getId());
}
}
}
}
jQuery zTree
1. 引入css和js
<link href="https://cdn.bootcss.com/zTree.v3/3.5.33/css/metroStyle/metroStyle.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/zTree.v3/3.5.33/js/jquery.ztree.core.min.js"></script>
2. html格式<ul id="myTree" class="ztree"></ul>
3. script
var setting = {
view: {
// 禁止多选
selectedMulti: false
},
async: {
// 开启异步加载功能
enable: true,
// 远程访问地址
url: "/contentCategory/treeData",
// 选择父节点时会自动将节点中的参数传回服务器再重新取结果
autoParam: ["id"]
}
};
// 初始化 zTree 控件
$.fn.zTree.init($("#myTree"), setting);
// 绑定事件
$("#modal_tree_confirm").bind("click", function () {
// 获取 zTree 控件
var zTree = $.fn.zTree.getZTreeObj("myTree");
// 获取已选中的节点
var nodes = zTree.getSelectedNodes();
if (nodes.length == 0) {
alert("请先选择一个父节点");
} else {
var node = nodes[0];
$("#categoryId").val(node.id);
$("#name").val(node.name);
$("#modal-tree").modal("hide");
}
});
4. java返回树状结构,name属性为显示的文件名,isParent会显示是否有下级
@ResponseBody
@PostMapping("/treeData")
public List<ContentCategory> treeData(@RequestParam(required = false,defaultValue = "0") Integer id){
ContentCategoryExample example = new ContentCategoryExample();
example.createCriteria().andParentIdEqualTo(id);
return contentCategoryService.selectByExample(example);
}
dropzone文件拖拽上传
1. 引入css和js
<link href="https://cdn.bootcss.com/dropzone/5.5.1/min/basic.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/dropzone/5.5.1/min/dropzone.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/dropzone/5.5.1/min/dropzone.min.js"></script>
2. example
<div id="dropz" class="dropzone"></div>
<script>
Dropzone.autoDiscover = false;
$("#dropz").dropzone({
url: "/upload",
dictDefaultMessage: '拖动文件至此或者点击上传', // 设置默认的提示语句
init: function () { //Dropzone 初始化的时候调用 添加事件监听器
this.on("success", function (file, data) {
// 上传成功触发的事件
$("#pic").val(data.filename);
});
}
});
</script>
3. java接收文件和配置
spring:
servlet:
multipart:
max-file-size: 10MB #文件最大上传
/**
* @author wzh
* @date 2019/9/27 - 16:00
*/
@Controller
public class UploadController {
private static final String UPLOAD_PATH = "static/upload/";
@ResponseBody
@RequestMapping("upload")
public Map<String,Object> uoload(MultipartFile file, HttpServletRequest request){
// 获取上传的原始文件名
String fileName = file.getOriginalFilename();
// 设置文件上传路径
String filePath = null;
try {
filePath = ResourceUtils.getURL("classpath:").getPath()+UPLOAD_PATH;
System.out.println(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 获取文件后缀
String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
// 判断并创建上传用的文件夹
File newFile = new File(filePath);
if (!newFile.exists()) {
newFile.mkdir();
}
newFile = new File(filePath, UUID.randomUUID()+fileSuffix);
try {
// 写入文件
file.transferTo(newFile);
} catch (IOException e) {
e.printStackTrace();
}
Map<String,Object> data = new HashMap<>();
//返回文件名
data.put("filename","/upload/"+newFile.getName());
return data;
}
}
wangEditor富文本编辑器
官方文档
1. 引入css和js
<link href="https://cdn.bootcss.com/wangEditor/10.0.13/wangEditor.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/wangEditor/10.0.13/wangEditor.min.js"></script>
2. 创建富文本
<div class="box-body">
<div class="form-group">
<label class="col-sm-2 control-label">详情</label>
<input id="content" name="content" hidden>
<div class="col-sm-10">
<div id="editor">
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
</div>
</div>
</div>
$(function () {
var E = window.wangEditor;
var editor = new E('#editor');
editor.create();
//点击提交时,将富文本内容以html标签格式放入content中
$("#btnSubmit").bind('click',function () {
$("#content").val(editor.txt.html());
});
});
3. wangEditor上传图片返回格式
{
// errno 即错误代码,0 表示没有错误。
// 如果有错误,errno != 0,可通过下文中的监听函数 fail 拿到该错误码进行自定义处理
"errno": 0,
// data 是一个数组,返回若干图片的线上地址
"data": [
"图片1地址",
"图片2地址",
"……"
]
}
- 上传业务代码
@Controller
public class UploadController {
private static final String UPLOAD_PATH = "static/upload/";
/**
* 上传
* @param file dropZone上传
* @param editorFile wangEditor上传
* @param request
* @return
*/
@ResponseBody
@RequestMapping("upload")
public Map<String,Object> uoload(MultipartFile file,MultipartFile editorFile, HttpServletRequest request){
MultipartFile myFile = file == null?editorFile:file;
// 获取上传的原始文件名
String fileName = myFile.getOriginalFilename();
// 设置文件上传路径
String filePath = null;
try {
filePath = ResourceUtils.getURL("classpath:").getPath()+UPLOAD_PATH;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 获取文件后缀
String fileSuffix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
// 判断并创建上传用的文件夹
File newFile = new File(filePath);
if (!newFile.exists()) {
newFile.mkdir();
}
newFile = new File(filePath, UUID.randomUUID()+fileSuffix);
try {
// 写入文件
myFile.transferTo(newFile);
} catch (IOException e) {
e.printStackTrace();
}
Map<String,Object> data = new HashMap<>();
//文件URI路径
String contentPath = "/upload/"+newFile.getName();
if(file == null){
data.put("errno",0);
data.put("data",new String[]{UrlUtils.getBaseUrl(request)+contentPath});
}else{
data.put("filename",contentPath);
}
return data;
}
}