前情说明:自己写的这个插件方式比较老套,主要是快速构建:图片上传是同表单提交一起提交,必须要引入layer
效果:
先上css代码:
.my-ui-img-div{
display: inline-block;
margin-left: 10px;
margin-top:5px;
border:1px solid #96c2f1;
background:#eff7ff;
border-radius:5px;
}
.my-ui-img-div .my-ui-img-file{
display: none;
}
.img-circle.my-ui-img{
width: 60px;
height: 60px;
}
因为用了bootstrap,所以用了bootstrap的属性:上面的img-circle就是,表示图片设置为圆形,如果没用的话,就用border-radius:5px;自己调整,同时后面用到的js里面这一块也要自己修改
在上html代码:
<!--追加图片列表样例,用在添加时-->
<div class="form-group">
<label class="col-sm-3 control-label">画廊图片:</label>
<div class="col-sm-8">
<div id="galleryDiv">
<div id="div_0" class="my-ui-img-div">
<input type="file" id="file_0" class="my-ui-img-file" onchange="replace_file_img('galleryDiv','div_','file_','files','img_',0)">
<a href="javascript:;"><img th:src="@{/img/img-add.png}" class="img-circle my-ui-img" id="img_0" onclick="click_file_img('file_',0)"></a>
</div>
</div>
</div>
</div>
说明一下:有两个方法:
replace_file_img('galleryDiv','div_','file_','files','img_',0)"
这个方法传入参数什么意思呢,div的id为galleryDiv这个里面的所有内容是一个整体
下面说下参数意思:
第一个参数:这个整体的div最外层div的id值,记住,该div内部的所有元素的id值都是前缀加索引的形式,建议索引从0开始
第二个参数:内部第二个div的前缀
第三个参数:隐藏的file文件id的前缀
第四各参数:这一组file文件统一的file的name属性值,因为是动态的,所以需要自己指定
第五个参数:显示图片id的前缀
第六个参数:所有元素的起始索引值
click_file_img('file_',0)"
这个方法更简单了,只需要传入file文件id的前缀和统一开始索引
因为用到了图片,所以图片如下:
js代码如下:
//保存删除图片个数的全局对象
var deleteObj = {deleteName:[],deleteNumber:[]};
//点击图片触发文件选择
function click_file_img(filePref,index) {
$("#"+filePref+index).click();
}
/**
* 替换图片,divId:最外层div的id值
* divPref,第二层div的id数值的前缀
* filePref:file输入框id的数值前缀
* fileName: 向后台传输的file文件的统一命名
* imgPref:图片索引的前缀
* index:统一的索引值,建议从0开始,name上面那些id的命名要遵循 前缀+索引 ,例如file_0,img_0
* imgName:这个参数不用管,不用传递这个参数值
*/
function replace_file_img(divId,divPref,filePref,fileName,imgPref,index,imgName) {
if(deleteObj.deleteName.indexOf(divId) === -1){
deleteObj.deleteName.push(divId);
deleteObj.deleteNumber.push(0);
}
var deleteIndex = deleteObj.deleteName.indexOf(divId);
var deleteNumber = deleteObj.deleteNumber[deleteIndex];
var length = $("#"+divId+" :file").length;//得到该部分文件的个数
var blob_img = $("#"+filePref+index)[0].files[0];
console.log(blob_img);
if((blob_img.type).indexOf("image/") === -1){
if(length === 1 || ((index+1-deleteNumber) === length)){
layer.msg("请选择图片");
}else{
layer.msg("请选择图片,因不是图片,所以该部分文件将被删除");
setTimeout(function(){
$("#"+divPref+index).remove();
deleteNumber++;
deleteObj.deleteNumber.splice(deleteIndex,1,deleteNumber);
},2000);
}
$("#"+filePref+index).attr("name","");//清空最后一个选择图标的name,不传往后台
return;
}
if($("#"+imgName+index).length > 0) {//判断隐藏域参数是否存在,存在就修改为false,表示不存在
var imgUrlDataUrl = $("#"+imgName+index).val();
var imgUrlData = JSON.parse(imgUrlDataUrl);
$("#"+imgName+index).val('["'+imgUrlData[0]+'","false"]');
$("#"+filePref+index).attr("name",fileName);//修改name值
}
var url = window.URL.createObjectURL(blob_img);
//替换url图片url
$("#"+imgPref+index).attr("src",url);
if((index+1-deleteNumber) === length){
$("#"+filePref+index).attr("name",fileName);//修改name值,因为在添加新的file是要讲之前的name值加上
add_file_img(divId,divPref,filePref,fileName,imgPref,index);
var elem = '<a href="javascript:;" onclick="img_file_delete(\''+divId+'\',\''+divPref+'\','+(index)+')" onmouseover="OverHint(this)" onmouseout="OutHint()">' +
'<img src="'+ctx+'img/img_remove.png" style="width: 20px;;position: relative;left: 0px;top:20px">' +
'</a>';
$("#"+imgPref+index).after(elem);
}
}
function add_file_img(divId,divPref,filePref,fileName,imgPref,index) {
var elem1 = '<div id="'+divPref+(index+1)+'"style="display: inline-block;margin-left: 10px;margin-top:5px;border:1px solid #96c2f1;background:#eff7ff;border-radius:5px">';
var elem2 = '<input type="file" id="'+filePref+(index+1)+'" style="display: none" onchange="replace_file_img(\''+divId+'\',\''+divPref+'\',\''+filePref+'\',\''+fileName+'\',\''+imgPref+'\','+(index+1)+')">';
var elem3 = '<a href="javascript:;"><img src="'+ctx+'img/img-add.png" class="img-circle" id="'+imgPref+(index+1)+'" style="width: 60px;height: 60px" onclick="click_file_img(\''+filePref+'\','+(index+1)+')"></a>';
var elem4 = '</div>';
$("#"+divPref+index).after(elem1+elem2+elem3+elem4);
}
/**
* 删除图片及文件
* @param divId 最外层div的id名字
* @param divPref 第二层div的id数值的前缀
* @param index 统一的索引值,建议从0开始,name上面那些id的命名要遵循 前缀+索引 ,例如file_0,img_0
*/
function img_file_delete(divId,divPref,index,imgName,fileName) {
var length = $("#"+divId+" :file").length;
var deleteIndex = deleteObj.deleteName.indexOf(divId);
var deleteNumber = deleteObj.deleteNumber[deleteIndex];
if((index+1-deleteNumber) != length){
if($("#"+imgName+index).length > 0) {//判断隐藏域参数是否存在,存在就修改为false,表示不存在
var imgUrlDataUrl = $("#"+imgName+index).val();
var imgUrlData = JSON.parse(imgUrlDataUrl);
$("#"+imgName+index).val('["'+imgUrlData[0]+'","false"]');
// $("#"+filePref+index).attr("name",fileName);//修改name值
}
$("#"+divPref+index).remove();
deleteNumber ++;
deleteObj.deleteNumber.splice(deleteIndex,1,deleteNumber);
layer.close(tip_index);
}
}
var tip_index;
function OverHint(obj) {
var that = obj;
tip_index = layer.tips('删除', that,{
tips : [ 1, '#00C9BA' ],
time : 4000
});
}
function OutHint(obj) {
layer.close(tip_index);
}
/**
* 在做修改时动态追击数据
* @param imgList 后台得到的图片列表数组
* @param imgName 数据库对应img字段对应的【用来接收数据集合的属性名】
* @param divId 最外层div的id值
* @param divPref 第二层div的id值的前缀名,不包括数字索引 这种格式为:前缀+索引 ,例如file_0,img_0
* @param filePref input文件框的id值的前缀名
* @param fileName 要向后台传输的file的统一命名
* @param imgPref img标签id的不包括索引值的前缀
*/
function appendImgListOnUpdate(imgList,imgName,divId,divPref,filePref,fileName,imgPref){
console.log("加载更新包;e");
var endIndex = 0;
if(imgList != null && imgList.length != 0){
imgList.forEach(function (currentValue, index, arr) {
console.log(currentValue);
var elem0 = '<input type="hidden" id="'+imgName+index+'" name="'+imgName+'" value=\'["'+currentValue+'","true"]\'>';
var elem1 = '<div id="'+divPref+(index)+'"style="display: inline-block;margin-left: 10px;margin-top:5px;border:1px solid #96c2f1;background:#eff7ff;border-radius:5px">';
var elem2 = '<input type="file" id="'+filePref+(index)+'" style="display: none" onchange="replace_file_img(\''+divId+'\',\''+divPref+'\',\''+filePref+'\',\''+fileName+'\',\''+imgPref+'\','+(index)+',\''+imgName+'\')">';
var elem3 = '<a href="javascript:;"><img src="'+currentValue+'" class="img-circle" id="'+imgPref+(index)+'" style="width: 60px;height: 60px" onclick="click_file_img(\''+filePref+'\','+(index)+')"></a>';
var elem4 = '</div>';
var elem = '<a href="javascript:;" onclick="img_file_delete(\''+divId+'\',\''+divPref+'\','+(index)+',\''+imgName+'\',\''+fileName+'\')" onmouseover="OverHint(this)" onmouseout="OutHint()">' +
'<img src="'+ctx+'img/img_remove.png" style="width: 20px;;position: relative;left: 0px;top:20px">' +
'</a>';
if(index === 0){
$("#"+divId).append(elem0+elem1+elem2+elem3+elem4);
$("#"+imgPref+index).after(elem);
endIndex ++;
}else {
$("#"+divPref+(index-1)).after(elem0+elem1+elem2+elem3+elem4);
$("#"+imgPref+index).after(elem);
endIndex ++;
}
})
}
var elem1 = '<div id="'+divPref+(endIndex)+'"style="display: inline-block;margin-left: 10px;margin-top:5px;border:1px solid #96c2f1;background:#eff7ff;border-radius:5px">';
var elem2 = '<input type="file" id="'+filePref+(endIndex)+'" style="display: none" onchange="replace_file_img(\''+divId+'\',\''+divPref+'\',\''+filePref+'\',\''+fileName+'\',\''+imgPref+'\','+(endIndex)+')">';
var elem3 = '<a href="javascript:;"><img src="'+ctx+'img/img-add.png" class="img-circle" id="'+imgPref+(endIndex)+'" style="width: 60px;height: 60px" onclick="click_file_img(\''+filePref+'\','+(endIndex)+')"></a>';
var elem4 = '</div>';
if(endIndex === 0){
$("#"+divId).append(elem1+elem2+elem3+elem4);
}else {
$("#"+divPref+(endIndex-1)).after(elem1+elem2+elem3+elem4);
}
}
说明一下:因为我没有直接写css引用class,所以你看到这里面追加的样式也在里面;所以你需要把里面的图片地址换一下,也就是上面两张图片的地址
以上是做增加的时候:
那么做修改呢,因为要将图片显示出来,删除也要做处理
所以修改时html代码:
<!--修改时样例,调用下方方法-->
<div class="form-group">
<label class="col-sm-3 control-label">画廊图片:</label>
<div class="col-sm-8">
<div id="galleryDiv">
</div>
</div>
</div>
是不是感觉更简单了
上面的js是通用的,引入就行了,但是你自己必须调用一个函数,见代码
<script type="text/javascript" th:inline="javascript">
var imgsList =[[${imgsList}]];//假设这是从后台查出来放在model中的数据,那么用这种方式可以拿到,取出图片列表数组数据,调用下方方法
//模拟数据,图片画廊做修改时,点开方法可以查看传输值的含义,可以对照添加时的标签结构理解
var imgList = ["http://pic37.nipic.com/20140113/8800276_184927469000_2.png","http://pic40.nipic.com/20140331/9469669_142840860000_2.jpg"];
appendImgListOnUpdate(imgList,'imgName','galleryDiv','div_','file_','files','img_');
</script>
看出来了吧,只需要调用appendImgListOnUpdate()方法即可:
* 在做修改时动态追击数据
* @param1 imgList 后台得到的图片列表数组
* @param2 imgName 数据库对应img字段对应的【用来接收数据集合的属性名】
* @param3 divId 最外层div的id值
* @param4 divPref 第二层div的id值的前缀名,不包括数字索引 这种格式为:前缀+索引 ,例如file_0,img_0
* @param5 filePref input文件框的id值的前缀名
* @param6 fileName 要向后台传输的file的统一命名
* @param7 imgPref img标签id的不包括索引值的前缀
看出来了吧,属性跟追加时是一样的,只是多了个要显示的图片集合和后台到时候接收这个集合的属性名
规则是这样的,因为所有的文件是统一提交的,所以在做删除的时候,这些接受到的集合是隐藏域,没显示的,隐藏域中的值是json格式的数据
显示效果:
这是隐藏域的内容,看出来了么,name,就是之前指定的后台接收这个存在的数据的属性,必须是个集合接收
这个拿到的数据在隐藏域中是json格式的,是个数组,第一个值表示的就是图片地址,第二个表示是否存在
开始的时候是存在的,所以是true
当我们删除之后呢
可以看到变成了false,这就很好办了,传到后台后,可以通过把这个集合里面的数据通过fastJson转换一下,就可以判断这条数据存在不存在了,不存在就将条数据删除了就行了,
我存在数据库中这样的多图是json格式存的,就是这样:["地址一",“地址二”],这种,所以我的处理方式是
新建集合,将这些为true的数据装进新的集合,false的不管,然后再将接受的file文件上传得到地址装进这个新集合,将这个新集合直接转换成json数据替换原有的该字段的数据
前端ajax一定要指定 mimeType: "multipart/form-data"
var data = getFormDateReturnForm("form-customer-add");//得到表单数据
var files = new Array();
$("input[name='files']").each(function(){
files.put($(this).files[0]);
});
data.append("files", files);
$.ajax({
cache: true,
type: "POST",
url: ctx + "vip/customer/add",
data: data,
contentType: false,
processData: false,
mimeType: "multipart/form-data",
async: false,
error: function (request) {
$.modal.alertError("系统错误");
},
success: function (data) {
$.operate.saveSuccess(JSON.parse(data));
}
});
//拿到表单中的数据,返回表单对象,传入的是form表单的id
function getFormDateReturnForm(id) {
var form = new FormData();
var t = $('#' + id).serializeArray();
$.each(t, function() {
form.append(this.name,this.value);
});
return form;
}
后台:这样就拿到相应的内容和file文件了
@LoggerManage("保存新增用户")
@RequiresPermissions("item:goods:add")
@PostMapping(value = "/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public JsonResult addSave(Goods goods,
@RequestPart(value = "files", required = false) MultipartFile[] files) throws IOException {
//里面的内容忽略
return ;
}