一、普通form表单上传图片
通过ajax上传图片到图床,以下实例为七牛云
<form id="formLogoID1" method="post" enctype="multipart/form-data" style="display: none;">
<input name="token" type="hidden" value="" id="shopTokenId" class="tokenClass" />
<input id="imagefile1" name="file" type="file" class="userfileClass" />
</form>
<label class="uploadImageClass" for="imagefile1">
<img class="layui-upload-img upload-default-img" src="./images/photo.png" id="shopLogoImageID1">
</label>
var uploadUrl1 = '';
$("#imagefile1").live("change", function() {
if (this.files.length != 0) {
var imgSize = (this.files[0].size / 1024 / 1024)
console.log(imgSize)
if (imgSize <= 3) {
ImageHandle1($("#shopLogoImageID1"), $("#formLogoID1").attr("id"));
} else {
layer.msg("图片大小超过3M,请重新选择", {
icon: 5
});
}
}
});
/**图片上传*/
function ImageHandle1(imgUrl, formID) {
var id = new FormData(document.getElementById(formID));
console.log(id)
$.ajax({
url: 'http://up.qiniu.com/',
type: 'POST',
data: id,
processData: false,
contentType: false,
success: function(res) {
console.log(res)
console.log("成功:" + JSON.stringify(res));
var srcUrl = domain + res.key;
console.log(srcUrl)
uploadUrl1 = srcUrl
imgUrl.attr("src", srcUrl);
imgUrl.css("width", "100%");
imgUrl.css("height", "100%");
console.log(uploadUrl1)
},
error: function(res) {
console.log("失败:" + JSON.stringify(res));
}
});
return false;
}
二、layui和七牛云
七牛云不支持批量上传图片,但是可以根据layui图片上传组件的异步功能,实现批量上传,但是图片上传是异步上传,当图片大小有过大差距的时候,存在图片上传顺序错乱的情况,可以在done()中根据index进行排序,然后在allDone()一起提交
<!-- 上传组件是在form表单里的-->
<div class="layui-form-item">
<label class="layui-form-label upload goods-desc" id="details"> 商品详情图:<span class="tips">不超过3M,格式为jpg,png</span></label>
<div class="layui-upload" style="height:auto">
<button type="button" class="layui-btn" id="ImageDetails">上传图片</button>
<div class="layui-upload-list multipleDetail showDetailsImg">
</div>
</div>
</div>
var DetailImg = new Array();
layui.use(['form', 'upload'], function() {
var form = layui.form;
var $ = layui.jquery;
var upload = layui.upload;
/*商品详情图片上传*/
var ImageDetails = upload.render({
elem: '#ImageDetails', //绑定元素
size: 3072,
multiple: true,
number: 30,
acceptMime: 'image/*',
url: 'http://up.qiniu.com', //该处为七牛云的上传接口
method: 'post',
data: {//主要是通过后台请求七牛云的url,获取token
key: function() {//自定义文件名
return 'aaa.png'
},
token: function() {
var token;
$.ajax({
async: false, //ajax 非异步获取taken
type: 'post',
url: url + 'type=third&method=qiniutoken&time=3600&space=images',//后台接口
success: function(res) {
if (DetailImg.length == 30) {
layer.msg('最多只能上传30张', {
icon: 5
});
} else {
console.log(res)
token = JSON.parse(res).token;
}
}
});
return token;
}
},
before: function(obj) {
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result) {
// console.log(file) //{name: "1.jpg" size: 140000}
// console.log(result) //{data:image/jpeg;base64,}
if (DetailImg.length == 30) {
layer.msg('最多只能上传30张', {
icon: 5
});
} else {
let imgList = `
<div class="img-box">
<img class="layui-upload-img upload-default-img" src="${result}" alt="${file.name}">
<div class="mb"></div>
<div class="remove">+</div>
</div>`
$('.showDetailsImg').append(imgList)
}
});
},
done: function(res, index, upload) {
console.log(res);
if (DetailImg.length == 30) {
layer.msg('最多只能上传30张', {
icon: 5
});
} else {//由于图片上传是异步上传,所以存在图片上传顺序错乱的情况,可以根据index,进行重新排序
var index = index.split('-')[1]
console.log(index)
if (index == 0) {
sortArr = new Array();
}
var url = domain + res.key
sortArr.push({
index: index,
url: url
})
console.log(sortArr)
}
},
allDone: function(obj) { //当文件全部被提交后,才触发
console.log(obj);
if (sortArr.length > 1) {
sortArr.sort(compare)
for (var i = 0; i < sortArr.length; i++) {
DetailImg.push(sortArr[i].url)
}
} else {
DetailImg.push(sortArr[0].url)
}
console.log(DetailImg)
},
error: function() {
//演示失败状态,并实现重传
// return layer.msg('error');
return;
}
});
})
/*
* 详情图 图片删除
*/
$(".showDetailsImg").on('mouseenter mouseleave', '.img-box', function() {
$(this).find(".remove").css({
opacity: 0.5
})
$(this).find(".mb").css({
opacity: 1
})
})
$(".showDetailsImg").on('mouseleave', '.img-box', function() {
$(this).find(".remove").css({
opacity: 0
})
$(this).find(".mb").css({
opacity: 0
})
})
$(".showDetailsImg").on('click', '.remove', function() {
var parents = $(this).parent()[0]
var index = $(".showDetailsImg .img-box").index(parents);
console.log(index);
console.log(DetailImg)
DetailImg.splice(index, 1)
console.log(DetailImg)
$(this).parent().remove()
})
/*排序*/
function compare(obj1, obj2) {
var a = obj1.index;
var b = obj2.index;
return a - b;
}
三、动态渲染数据表格时,添加图片上传组件
先上图片
重点:在渲染数据表格的时候,需要一起把上传按钮的点击事件一起渲染
<div class="layui-form-item ">
<label class="layui-form-label goods-desc">商品规格:</label>
<div class="specs">
<div class="box">
<div class="layui-input-block" style="margin-left: 15px;display: flex;">
<input type="text" name="network" autocomplete="off" placeholder="网络" class="layui-input" id="network" style="width: 50px;margin-right: 20px;">
<input type="text" name="newNetwork" autocomplete="off" class="layui-input" id="newNetwork" style="width: 150px;margin-right: 20px;">
<button type="button" class="layui-btn layui-btn-primary" style="width: 50px;padding: 0;" id="addNewNetwork">新增</button>
</div>
<div class="showAddNewNetwork showAdd"></div>
</div>
<div class="box">
<div class="layui-input-block" style="margin-left: 15px;display: flex;">
<input type="text" name="memory" autocomplete="off" placeholder="内存" class="layui-input" id="memory" style="width: 50px;margin-right: 20px;">
<input type="text" name="newMemory" autocomplete="off" class="layui-input" id="newMemory" style="width: 150px;margin-right: 20px;">
<button type="button" class="layui-btn layui-btn-primary" style="width: 50px;padding: 0;" id="addNewMemory">新增</button>
</div>
<div class="showAddNewMemory showAdd"></div>
</div>
<div class="box">
<div class="layui-input-block" style="margin-left: 15px;display: flex;">
<input type="text" name="color" autocomplete="off" placeholder="颜色" class="layui-input" id="color" style="width: 50px;margin-right: 20px;">
<input type="text" name="newColor" autocomplete="off" class="layui-input" id="newColor" style="width: 150px;margin-right: 20px;">
<button type="button" class="layui-btn layui-btn-primary" style="width: 50px;padding: 0;" id="addNewColor">新增</button>
</div>
<div class="showAddNewColor showAdd"></div>
</div>
<button type="button" class="layui-btn" id="save">保存</button>
</div>
</div>
<script type="text/html" id="showGoodsList">
<table>
<thead>
<tr>
<th>{{d.title1}}</th>
<th>{{d.title2}}</th>
<th>{{d.title3}}</th>
<th>售价</th>
<th>库存</th>
</tr>
</thead>
<tbody>
{{# layui.each(d.data, function(index, item){ }}
<tr>
<td>{{item.network}}</td>
<td>{{item.memory}}</td>
<td class="picBox">
<div class="color">
{{item.color}}
</div>
<div class="layui-upload addUpload">
<button type="button" class="layui-btn eachGoodsImgBtn" style="float: left; margin: 35px 10px 0 0">上传图片</button>
<input class="layui-upload-file" type="file" accept="image/*" name="file">
<div class="layui-upload-list">
<img class="layui-upload-img ShowEachGoodsImg">
</div>
</div>
</td>
<td class="eachPrice">
<input type="text" autocomplete="off" class="layui-input" placeholder="999">
</td>
<td class="eachStock">
<input type="text" autocomplete="off" class="layui-input" placeholder="999">
</td>
</tr>
{{# }); }}
</tbody>
</table>
<script>
var network = '';
var networkArr = new Array();
var memory = '';
var memoryArr = new Array();
var color = '';
var colorArr = new Array();
var goodsList = '';
var trIndex = '';
layui.use(['form', 'upload', 'laytpl'], function() {
var form = layui.form;
var layer = layui.layer;
var $ = layui.jquery;
var upload = layui.upload;
var laytpl = layui.laytpl;
//按钮保存生成规格表格
$("#save").click(function() {
var newArr = new Array();
if (network == '') {
network = "网络"
}
if (memory == '') {
memory = "内存"
}
if (color == '') {
color = "颜色"
}
if (networkArr == '' || memoryArr == '' || colorArr == '' || network == '' || memory == '' || color == '') {
layer.msg("请先添加内容,再保存", {
icon: 5
});
} else {
for (var i = 0; i < networkArr.length; i++) {
for (var j = 0; j < memoryArr.length; j++) {
for (var k = 0; k < colorArr.length; k++) {
newArr.push({
network: networkArr[i],
memory: memoryArr[j],
color: colorArr[k],
imgurl: '',
price: '',
stock: ''
})
}
}
}
console.log(newArr)
goodsList = {
title1: network,
title2: memory,
title3: color,
data: newArr
}
console.log(goodsList)
var getTpl = showGoodsList.innerHTML;
var view = document.getElementById('goodslist');
laytpl(getTpl).render(goodsList, function(html) {
view.innerHTML = html;
});
//重点:在渲染表格的时候,需要渲染upload组件,否则按钮的点击事件是无效的
uploadImgRender(".eachGoodsImgBtn");
}
})
//获取tr的索引
$("#goodslist").on("click", ".eachGoodsImgBtn", function() {
var gettr = $(this).parent().parent().parent()[0];
trIndex = $("#goodslist tbody tr").index(gettr);
console.log(gettr)
console.log(trIndex)
})
/*封装表格里单个图片上传*/
function uploadImgRender(e) {
var uploadEachGoods = upload.render({
elem: e, //绑定元素
size: 3072,
acceptMime: 'image/*',
url: 'http://up.qiniu.com/', //上传接口
method: 'post',
data: {
key: function() {//自定义文件名
return 'aaa.png'
},
token: function() {
var token;
$.ajax({
async: false, //ajax 非异步获取taken
type: 'post',
url: url + 'type=third&method=qiniutoken&time=3600&space=images',
success: function(res) {
console.log(res)
token = JSON.parse(res).token;
}
});
return token;
}
},
before: function(obj) {
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result) {
$("#goodslist tbody tr").eq(trIndex).find(".layui-upload-list").css({
'display': 'block'
})
$("#goodslist tbody tr").eq(trIndex).find(".ShowEachGoodsImg").attr('src', result)
});
},
done: function(res, index, upload) {
console.log(res);
for (var i = 0; i < goodsList.data.length; i++) {
if (i == trIndex) {
goodsList.data[i].imgurl = domain + res.key; //damain 来自qiniu/formdata.js
}
}
console.log(goodsList)
},
error: function() {
//演示失败状态,并实现重传
return layer.msg('error');
}
});
}
})
三、layui 图片上传时,判断图片长宽和自定义名字
layui再上传图片时,若是需要判断上传图片的长宽,可以在上传前继续判断,选择
choose: function(obj){}
,同时要关闭自动上传,即auto: false
,批量上传图片时,图片渲染要放在choose中
<!-- 上传图片-->
<div class="layui-form-item">
<label class="layui-form-label upload goods-desc"> 小程序logo:</label>
<div class="layui-upload">
<button type="button" class="layui-btn" id="appletsImg">上传图片</button>
<label style="width: 500px;color: red;margin-left: 20px;">注:小程序logo图标,格式必须为:png,jpeg,jpg,建议上传像素为180*180,图片最大为256KB</label>
<div class="layui-upload-list">
<img class="layui-upload-img" id="ShowThirdImg">
</div>
</div>
</div>
var suffix=""; //获取上传图片的后缀名
var img="";//需要获取的图片
// 图片尺寸
var imgSize = {
width: 180,
height: 180,
size: 256
};
//方法调用
uploadImgRender("#appletsImg", "#ShowThirdImg", imgSize, function(res) {
img = res
});
// 封装图片上传功能
function uploadImgRender(elemBtn, showImg, size, callback) {
var ImageSingular = upload.render({
elem: elemBtn, //绑定元素
size: size.size,
acceptMime: 'image/jpg, image/jpeg, image/png',
url: 'http://up.qiniu.com/', //上传接口
method: 'post',
auto: false, //要在choose中判断上传图片大小时,auto参数必须设置为false
data: {
key: function() { //自定义文件名
return getNowFormatDate() + lastThree() + "." + suffix
},
token: function() {
var token;
$.ajax({
async: false, //ajax 非异步获取taken
type: 'post',
url: url + 'type=third&method=qiniutoken&time=3600&space=images',//后台接口
success: function(res) {
console.log(res)
token = JSON.parse(res).token;
}
});
return token;
}
},
choose: function(obj) { //上传前选择回调方法
// var files = obj.pushFile();//将每次选择的文件追加到文件队列
var flag = true;
obj.preview(function(index, file, result) {//预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
//obj.resetFile(index, file, '123.jpg'); //重命名文件名,layui 2.3.0 开始新增
//这里还可以做一些 append 文件列表 DOM 的操作
// obj.upload(index, file); //满足条件调用上传方法
//delete files[index]; //删除列表中对应的文件,一般在某个事件中使用
console.log(file)
suffix = file.name.split('.')[1];//获取上传图片的后缀名
var img = new Image();
img.src = result;
img.onload = function(res) { //初始化夹在完成后获取上传图片宽高,判断限制上传图片的大小。
if (size.width == 0 && size.height == 0) {
obj.upload(index, file); //满足条件调用上传方法
} else if (size.width != 0 && size.height != 0) {
if (img.width == size.width && img.height == size.height) {
obj.upload(index, file); //满足条件调用上传方法
} else {
flag = false;
layer.msg(`您上传的小图大小必须是${size.width}*${size.height}尺寸!`);
return false;
}
}
}
return flag;
});
},
before: function(obj) {
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result) {
//多张图片上传时,应该放在choose中
$(showImg).attr('src', result); //图片链接(base64)
});
},
done: function(res, index, upload) {
console.log(res);
var saveImg = domain + res.key; //damain 来自qiniu/formdata.js
console.log(saveImg)
callback(saveImg);
},
error: function() {
//演示失败状态,并实现重传
return layer.msg('error');
}
});
}
//生成图片的随机数
function getNowFormatDate() {
var day = new Date();
var Year = 0;
var Month = 0;
var Day = 0;
var Hour = 0;
var Minute = 0;
var Second = 0;
var CurrentDate = "";
Year = day.getFullYear(); //支持IE和火狐浏览器.
Month = day.getMonth() + 1;
Day = day.getDate();
Hour = day.getHours();
Minute = day.getMinutes();
Second = day.getSeconds();
CurrentDate += Year; //CurrentDate =CurrentDate+ Year
if (Month >= 10) {
CurrentDate += Month;
} else {
CurrentDate += "0" + Month;
}
if (Day >= 10) {
CurrentDate += Day
} else {
CurrentDate += "0" + Day;
}
CurrentDate = CurrentDate + Hour + Minute + Second;
return CurrentDate;
}
function lastThree() {
var lastThree = '';
for (var i = 0; i < 3; i++) {
lastThree += Math.floor(Math.random() * 10);
}
return lastThree
}
四、layui 图片上传
1.选择文件的回调
在文件被选择后触发,该回调会在 before 回调之前。一般用于非自动上传(即 auto: false )的场景,比如预览图片等。
upload.render({
elem: '#id'
,url: '/api/upload/'
,auto: false //选择文件后不自动上传
,bindAction: '#testListAction' //指向一个按钮触发上传
,choose: function(obj){
//将每次选择的文件追加到文件队列
var files = obj.pushFile();
//预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
obj.preview(function(index, file, result){
console.log(index); //得到文件索引
console.log(file); //得到文件对象
console.log(result); //得到文件base64编码,比如图片
//obj.resetFile(index, file, '123.jpg'); //重命名文件名,layui 2.3.0 开始新增
//这里还可以做一些 append 文件列表 DOM 的操作
//obj.upload(index, file); //对上传失败的单个文件重新上传,一般在某个事件中使用
//delete files[index]; //删除列表中对应的文件,一般在某个事件中使用
});
}
});
2.文件上传前的回调
在 choose 回调之后、done/error 回调之前触发。返回的参数完全类似 choose 回调。一般用于上传完毕前的loading、图片预览等。
upload.render({
elem: '#id'
,url: '/api/upload/'
,before: function(obj){ //obj参数包含的信息,跟 choose回调完全一致,可参见上文。
layer.load(); //上传loading
}
,done: function(res, index, upload){
layer.closeAll('loading'); //关闭loading
}
,error: function(index, upload){
layer.closeAll('loading'); //关闭loading
}
});
3.上传接口请求成功的回调
在上传接口请求完毕后触发,但文件不一定是上传成功的,只是接口的响应状态正常(200)。回调返回三个参数,分别为:服务端响应信息、当前文件的索引、重新上传的方法
upload.render({
elem: '#id'
,url: '/api/upload/'
,done: function(res, index, upload){
//假设code=0代表上传成功
if(res.code == 0){
//do something (比如将res返回的图片链接保存到表单的隐藏域)
}
//获取当前触发上传的元素,一般用于 elem 绑定 class 的情况,注意:此乃 layui 2.1.0 新增
var item = this.item;
//文件保存失败
//do something
}
});
4.上传请求失败的回调
当请求上传时出现异常时触发(如网络异常、404/500等)。回调返回两个参数,分别为:当前文件的索引、重新上传的方法
upload.render({
elem: '#id'
,url: '/api/upload/'
,error: function(index, upload){
//当上传失败时,你可以生成一个“重新上传”的按钮,点击该按钮时,执行 upload() 方法即可实现重新上传
}
});
5.多文件上传完毕后的状态回调
只有当开启多文件时(即 multiple: true),该回调才会被触发。回调返回一个 object 类型的参数,包含一些状态数据:
upload.render({
elem: '#id'
,url: '/api/upload/'
,multiple: true
,allDone: function(obj){ //当文件全部被提交后,才触发
console.log(obj.total); //得到总文件数
console.log(obj.successful); //请求成功的文件数
console.log(obj.aborted); //请求失败的文件数
}
,done: function(res, index, upload){ //每个文件提交一次触发一次。详见“请求成功的回调”
}
});
6.文件上传进度的回调
在网速一般的情况下,大文件的上传通常需要一定时间的等待,而浏览器并不会醒目地告知你它正在努力地上传中,此时为了提升用户体验,我们可以通过该回调制作一个进度条。
upload.render({
elem: '#id'
,url: '/api/upload/'
,progress: function(n, elem){
var percent = n + '%' //获取进度百分比
element.progress('demo', percent); //可配合 layui 进度条元素使用
//以下系 layui 2.5.6 新增
console.log(elem); //得到当前触发的元素 DOM 对象。可通过该元素定义的属性值匹配到对应的进度条。
}
});