前端使用jQuery完成图片的上传,后端使用Java接收图片文件
具体实现步骤:
- 使用HTML和CSS进行页面的布局,并引入jQuery库;
- 使用三个input标签,类型均为type="file"的标签,并命名好相对应的id,这个id可以命名的有规律些,便于后面的循环赋值,特别说明:input标签中加入multiple属性,则可同时选择多张图片;
- 在全局中设置好需要上传后存储的图片参数数组,我这里是以上传电商类图片信息为例子,所以用了三个数组,如果需要上传更多类别,请自行添加;
- 调用jQuery的change方法,将每次上传的图片进行逻辑处理
- 在界面上进行图片预览,动态的使用jQuery编写显示的逻辑方法,包括一次可以上传多张,上传后隐藏掉上传按钮等逻辑方法;
- 若需要移除图片,则根据传入的图片id和类型,删除对应的数组中装载的图片参数即可;
- 使用jQuery调用Ajax方法,将图片信息传入后端,这里需要注意的是,传入的图片参数,具体见下方js代码:
1、HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>批量上传图片</title>
<script src="https://www.jq22.com/jquery/jquery-2.1.1.js"></script>
</head>
<body>
<!--封面图片-->
<div class="level">
<div class="left-width">
<label>
<span class="red">*</span> 封面图片:
</label>
</div>
<div class="right-width">
<div class="custom-box">
<div id="topTitle1" class="custom-title hide">
<div class="custom-count" id="totalImg1">总共0张图片(0.00K)</div>
<div class="custom-add">
<span>继续添加</span>
<input type="file" accept="image/*" class="cover-file" data-type="1">
</div>
</div>
<div class="custom-center-title">
<ul class="custom-ul" id="image1"></ul>
<div id="showBtn1" class="custom-center">
<i class="fa fa-image custom-icon"></i>
<div class="custom-file">
<span>点击选择图片</span>
<input type="file" accept="image/*" class="cover-file" data-type="1">
</div>
<span class="custom-tips">最多可选择 1 张图片呦~</span>
</div>
</div>
</div>
</div>
</div>
<!--轮播图片-->
<div class="level">
<div class="left-width">
<label>
<span class="red">*</span> 轮播图片:
</label>
</div>
<div class="right-width">
<div class="custom-box">
<div id="topTitle2" class="custom-title hide">
<div class="custom-count" id="totalImg2">总共0张图片(0.00K)</div>
<div class="custom-add">
<span>继续添加</span>
<input type="file" accept="image/*" class="cover-file" data-type="2">
</div>
</div>
<div class="custom-center-title">
<ul class="custom-ul" id="image2"></ul>
<div id="showBtn2" class="custom-center">
<i class="fa fa-image custom-icon"></i>
<div class="custom-file">
<span>点击选择图片</span>
<input type="file" accept="image/*" multiple class="cover-file" data-type="2">
</div>
<span class="custom-tips">最多可选择 3 张图片呦~</span>
</div>
</div>
</div>
</div>
</div>
<!--详情图片-->
<div class="level">
<div class="left-width">
<label>
<span class="red">*</span> 详情图片:
</label>
</div>
<div class="right-width">
<div class="custom-box">
<div id="topTitle3" class="custom-title hide">
<div class="custom-count" id="totalImg3">总共0张图片(0.00K)</div>
<div class="custom-add">
<span>继续添加</span>
<input type="file" accept="image/*" class="cover-file" data-type="3">
</div>
</div>
<div class="custom-center-title">
<ul class="custom-ul" id="image3"></ul>
<div id="showBtn3" class="custom-center">
<i class="fa fa-image custom-icon"></i>
<div class="custom-file">
<span>点击选择图片</span>
<input type="file" accept="image/*" multiple class="cover-file" data-type="3">
</div>
<span class="custom-tips">最多可选择 5 张图片呦~</span>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
2、CSS代码
<style>
.level {
display: flex;
flex-direction: row;
margin: 10px 0;
}
.red {
color: red
}
.left-width {
width: 8%;
text-align: center
}
.right-width {
width: 92%;
}
.custom-box {
background-color: #fdfdfd;
border: 1px solid #dde1e8;
border-radius: 2px;
padding: 15px 0
}
.custom-file {
position: relative;
display: inline-block;
background: #1e5edb;
border: 1px solid #1e5edb;
border-radius: 4px;
padding: 4px 8px;
overflow: hidden;
color: white;
text-decoration: none;
text-indent: 0;
line-height: 20px;
}
.custom-add {
position: relative;
display: inline-block;
margin-right: 18px;
margin-bottom: 15px;
background-color: #ffffff;
border: 1px solid #cfcfcf;
color: #565656;
text-decoration: none;
text-indent: 0;
line-height: 20px;
border-radius: 4px;
padding: 4px 8px;
overflow: hidden;
}
.cover-file {
position: absolute;
font-size: 100px;
right: 0;
top: 0;
opacity: 0;
}
.custom-ul {
display: block;
white-space: nowrap;
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
}
.custom-li {
position: relative;
width: 110px;
height: 110px;
float: left;
list-style-type: none;
margin: 10px;
}
.custom-icon {
color: #dfdfdf;
font-size: 52px !important;
margin-bottom: 10px
}
.custom-img {
width: 100%;
height: 110px;
overflow: hidden;
vertical-align: middle;
border-radius: 5px;
border: 1px solid #f1f1f1;
}
.custom-trash {
position: absolute;
width: 100%;
border-radius: 5px 5px 0 0;
padding: 5px;
color: white;
font-size: 16px !important;
text-align: right;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.custom-trash:hover {
opacity: 1;
}
.custom-del:hover {
color: red;
font-size: 14px !important;
cursor: pointer;
}
.custom-load {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: red;
font-size: 12px !important;
text-align: center;
color: #ffffff;
padding: 3px 0;
border-radius: 0 0 5px 5px;
}
.custom-title {
display: flex;
justify-content: space-between;
align-items: center
}
.custom-center-title {
margin: 3px 18px;
border: 2px dashed #e6e6e6
}
.custom-count {
margin-left: 18px;
font-size: 14px !important;
color: #666
}
.custom-tips {
color: #cccccc;
font-size: 14px !important;
margin-top: 10px
}
.custom-center {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 50px 0
}
.hide {
display: none;
}
</style>
3、js代码
<script>
/**
* 定义三个全局变量的数组
* */
let imgList1 = [], imgList2 = [], imgList3 = [];
/**
* 上传图片监听
* 其中type为上传三种图片的类型区分,便于下面数据的处理
* 代码有些冗余了,可自行整理优化
* */
$('.cover-file').on('change', function (e) {
let tag = e.currentTarget.dataset.type;
let img = e.target.files;
if (tag == 1) {
for (let i = 0; i < img.length; i++) {
img[i].imgType = '0';
imgList1 = imgList1.concat(img[i]);
}
imgShow(imgList1, '1');
}
if (tag == 2) {
for (let i = 0; i < img.length; i++) {
if (i < 3) {
img[i].imgType = '1';
imgList2 = imgList2.concat(img[i]);
}
}
imgShow(imgList2, '2');
}
if (tag == 3) {
for (let i = 0; i < img.length; i++) {
if (i < 5) {
img[i].imgType = '2';
imgList3 = imgList3.concat(img[i]);
}
}
imgShow(imgList3, '3');
}
});
/**
* 显示图片列表
* 将选择的图片进行预览,动态加载图片列表
* */
function imgShow(attr, tag) {
let html = '', total = 0;
let windowURL = window.URL || window.webkitURL;
for (let i = 0; i < attr.length; i++) {
let dataURL = windowURL.createObjectURL(attr[i]);
html += '<li class="custom-li">' +
'<div class="custom-trash" οnclick="removeImg(' + i + ',' + tag + ')"><span class="custom-del">删除</span></div>' +
'<div><img class="custom-img" src="' + dataURL + '"></div>' +
'<div class="custom-load">等待上传</div>' +
'</li>';
windowURL.revokeObjectURL(attr[i]);
total += attr[i].size;
}
let size = (total / 1024).toFixed(2);
$('#totalImg' + tag).text('总共' + attr.length + '张图片(' + size + 'K)');
switch (tag) {
case '1':
if (attr.length > 0) {
$('#showBtn' + tag).addClass('hide');
} else {
$('#showBtn' + tag).removeClass('hide');
$('#topTitle' + tag).addClass('hide');
}
break;
case '2':
if (attr.length > 0) {
if (attr.length < 3) {
$('#showBtn' + tag).addClass('hide');
$('#topTitle' + tag).removeClass('hide');
} else {
$('#showBtn' + tag).addClass('hide');
$('#topTitle' + tag).addClass('hide');
}
} else {
$('#showBtn' + tag).removeClass('hide');
$('#topTitle' + tag).addClass('hide');
}
break;
default:
if (attr.length > 0) {
if (attr.length < 5) {
$('#showBtn' + tag).addClass('hide');
$('#topTitle' + tag).removeClass('hide');
} else {
$('#showBtn' + tag).addClass('hide');
$('#topTitle' + tag).addClass('hide');
}
} else {
$('#showBtn' + tag).removeClass('hide');
$('#topTitle' + tag).addClass('hide');
}
break;
}
$('#image' + tag).html(html);
}
/**
* 移除图片监听
* 传入需要移除的图片参数信息
* */
function removeImg(obj, tag) {
var ask = confirm("确认删除该图片吗?");
if (ask) {
if (tag == '1') {
$.each(imgList1, (index) => {
if (index == obj) {
imgList1.splice(index, 1)
}
});
imgShow(imgList1, tag);
}
if (tag == '2') {
$.each(imgList2, (index) => {
if (index == obj) {
imgList2.splice(index, 1)
}
});
imgShow(imgList2, tag);
}
if (tag == '3') {
$.each(imgList3, (index) => {
if (index == obj) {
imgList3.splice(index, 1)
}
});
imgShow(imgList3, tag);
}
}
}
/**
* 提交保存图片监听
* */
$('#submitData').on('click', function () {
// 判断上传的图片是否为空
let attr = (imgList1.concat(imgList2)).concat(imgList3);
if (attr.length < 1) {
js.showMessage('上传的图片信息不能为空呦~');
return;
}
//将文件对象传入files键中,这个files和后端接收的参数名一样,具体看下面给出的后端接口代码
let paramsImg = new FormData();
for (let i = 0; i < attr.length; i++) {
paramsImg.append('imgType', attr[i].imgType);
paramsImg.append('files', attr[i]);
}
js.confirm('确认提交吗?', function () {
$.ajax({
url: 'http://localhost:8080/testApi',
type: 'POST',
data: paramsImg,
dataType: 'JSON',
cache: false, // 不缓存
processData: false, // jQuery不要去处理发送的数据
contentType: false, // jQuery不要去设置Content-Type请求头
mimeType: "multipart/form-data",
success: function (res) {
// 返回成功后的处理逻辑
console.log(res);
}
});
});
})
</script>
4、Java接口代码片段
/**
* 保存图片
*/
@PostMapping(value = "testApi")
@ResponseBody
public String saveItem(@RequestParam(value = "files", required = false) MultipartFile[] files, String imgType) {
if (files.length > 0) {
String[] attr = imgType.split(","); // 图片类型
for (int i = 0; i < files.length; i++) {
// 具体上传的的图片逻辑
}
return "success";
} else {
return "fail";
}
}
里面很多冗余代码,可根据自己需求进行优化呦