小程序前端
初步实现上传图片
任务目标为,在微信小程序前端实现图片上传和预览功能,能单独删除已上传的图片。正常情况下,这一任务需要两步完成。
- 设置参数,使用wx.uploadFile向文件服务器/云储存 上传图片;上传成功后服务器返回图片保存的路径/URL
- 将返回的路径/URL放入表单中提交
也就说,每一张图片的添加和删除,都需要调用一次后端接口,给后端的压力较大。现改为前端图片的上传和删除只在前端发生,将需要上传的图片地址保存在前端数组中,“上传”和“删除”变成单纯对字符串数组的操作,在最后上传表单内容时,将存储图片的数组一同上传即可。
data: {
links_type:'',
cameraList:[],
imgList: [],//存储图片临时地址
uploadcurrent: 0,
uploadImgList: [],//存储图片成功上传后,后端返回的服务器上图片存储位置
},
//关于调用视频和图片
// 点击添加选择
chooseSource: function () {
var _this = this;
wx.showActionSheet({
itemList: ["拍照", "从相册中选择"],
itemColor: "#000000",
success: function (res) {
if (!res.cancel) {
if (res.tapIndex == 0) {
_this.imgWShow("camera") //拍照
} else if (res.tapIndex == 1) {
_this.imgWShow("album") //相册
}
}
}
})
},
// 点击调用手机相册/拍照
imgWShow: function (type) {
var _this = this;
let len = 0;
if (_this.data.imgList != null) {
len = _this.data.imgList.length
}
wx.chooseImage({
count: 10 - len,
sizeType: ['original', 'compressed'],
sourceType: [type],
success: function (res) {
wx.showToast({
title: '正在上传...',
icon: "loading",
mask: true,
duration: 1000
})
var imgList = res.tempFilePaths
let tempFilePathsImg = _this.data.imgList
var tempFilePathsImgs = tempFilePathsImg.concat(imgList)
_this.setData({
imgList: tempFilePathsImgs //将图片的临时地址存储到全局变量imgList中
})
//,()=>_this.uploadimagFile() 本来是在这个地方执行上传后端操作的
},
fail: function () {
wx.showToast({
title: '图片上传失败',
icon: 'none'
})
return;
}
})
},
// 预览图片
previewImg: function (e) {
let index = e.target.dataset.index;
let _this = this;
wx.previewImage({
current: _this.data.imgList[index],
urls: _this.data.imgList
})
},
/**
* 点击删除图片 也就是从imglist中删除对应图片临时地址
*/
deleteImg: function (e) {
var _this = this;
var imgList = _this.data.imgList;
var current=_this.data.uploadcurrent;
var index = e.currentTarget.dataset.index; //获取当前点击图片下标
wx.showModal({
title: '提示',
content: '确认要删除该图片吗?',
success: function (res) {
if (res.confirm) {
imgList.splice(index, 1);
current=current-1;
} else if (res.cancel) {
return false
}
_this.setData({
imgList,
uploadcurrent:current
})
}
})
},
// 图片上传服务
uploadimagFile(){
const that=this;
let imgListData = that.data.imgList;
let current=that.data.uploadcurrent;
console.log(imgListData)
for(let i=0;i<imgListData.length;i++){//循环遍历整个imglist,因为uploadFile方法只能一次上传一张图片
console.log(imgListData[i])
wx.uploadFile({
url: getApp().globalData.serverBaseUrl+'/Applets/wechatImg',//后端对应接口
filePath:imgListData[i],
name:'image',
success(res) {
console.log("返回的信息",res.data.url)
//let imgPath_url=JSON.parse(res.data).data.path+JSON.parse(res.data).data.img
let imgPath_url=JSON.parse(res.data).url
console.log(imgPath_url)
current=imgListData.length
that.data.uploadImgList=that.data.uploadImgList.concat(imgPath_url)
//wx.setStorageSync('imgPath', that.data.uploadImgList)
console.log(that.data.uploadImgList)
that.setData({
uploadImgList:that.data.uploadImgList,//将后端返回的图片地址存入uploadImgList
//imgList:'',
})
wx.showToast({
title: '上传数据成功',
icon: 'success',
duration: 500,
success: function () {
// setTimeout(() => {
// wx.navigateBack()
// }, 300)
}
})
},
fail: function (res) {
console.log('接口调用失败');
console.log(res);
}
})
}
},
/**
* 上传表单的方法的部分代码
*/
console.log('form发生了submit事件,携带数据为:', e.detail.value);
var that=this;
var shoptoken=that.data.token;
console.log(shoptoken);
this.uploadimagFile();//在这里调用上传图片的方法
console.log(that.data.uploadImgList);
console.log(that.data.videoPath_links)
setTimeout(()=>
{
wx.request({
url:getApp().globalData.serverBaseUrl+'/Applets/setShopKeeper',
//url:getApp().globalData.serverBaseUrl+'/Applets/login',
header: {'content-type': 'application/x-www-form-urlencoded'},
method: 'POST',
data: {
'shopposition': e.detail.value.shopposition,
'shopname': e.detail.value.shopname,
'realname': e.detail.value.realname,
'mobile': e.detail.value.mobile,
'maincontent': e.detail.value.maincontent,
'flow': e.detail.value.flow,
'token':shoptoken,
'photo':that.data.uploadImgList,//将服务器端图片地址随表单一起上传
},
success: function (res) {
if(res.data.code == 200){
wx.showModal({
title: '提示',
content: res.data.msg,
showCancel: true,
success: function (res) {
}
})
// wx.navigateBack({
// })
}else{
wx.showModal({
title: '提示',
content: res.data.msg,
showCancel: false,
success: function (res) {
}
})
}
},
fail:function(res){
console.log(res);
}
})
}, 500)
效果展示:
上传表单时要注意,wx.request是异步发生的,逻辑上需要图片先上传到后端,后端返回图片存储地址,再将地址存入前端变量中,最后表单上传到后端,但wx.request是异步发生的,也就说有可能uploadimagFile()并没有完全执行完,表单就上传到后端,导致最后图片能全都上传到后端,但数据库中表单内图片地址不全。
一开始尝试如上面代码那样使用setTimeout,即在uploadimagFile()与wx.request间增加一个延迟来解决以上问题,很明显,这种解决方法并不稳定,在网络不那么理想或者图片较多的情况下,request方法发生时经常图片上传仍没有完成,而加大延迟会明显影响用户体验。
解决wx.request异步问题
回调
最简单的解决方案,就是把需要使用异步数据的函数写在回调里,例如:
wx.request({
url: 'url', // 这里填写的接口地址
data: { }, //这里填写需要传输的数据
method: 'POST', // 这里也可以是'GET'
header: {
'content-type': 'application/json', // 默认值
'session': ‘sessionid’ //这里一般可能用不到,通过session来确认用户身份,比较安全的用法
},
success:function(res) {
console.log(res.data)
//这里再次发送请求
wx.request({
url: 'url', // 这里填写的接口地址
data: { }, //这里填写需要传输的数据
method: 'POST', // 这里也可以是'GET'
header: {
'content-type': 'application/json', // 默认值
'session': ‘sessionid’ //这里一般可能用不到,通过session来确认用户身份,比较安全的用法
},
success:function(res) {
console.log(res.data)
}
})
}
})
看起来很容易理解,两个异步函数嵌套起来,似乎感觉还不是很乱,但如果4个5个呢?
Promise+ASYNC\AWAIT
添加微信小程序对es6与es7的支持
在需要使用Promise+ASYNC\AWAIT的JS下导入
然后我们就能正常使用Promise以及ASYNC\AWAIT了。
首先,修改我们的uploadimagFile()方法:
uploadimagFile(){
const that=this;
return new Promise((resolve,reject)=>{//在这里使用return
let imgListData = that.data.imgList;
//let current=that.data.uploadcurrent;
console.log(imgListData)
//console.log("current当前",current)
for(let i=0;i<imgListData.length;i++){
console.log(imgListData[i])
wx.uploadFile({
url: getApp().globalData.serverBaseUrl+'/Applets/wechatImg',
filePath:imgListData[i],
name:'image',
success(res) {
console.log("返回的信息",res.data)
let imgPath_url=JSON.parse(res.data).url
console.log(imgPath_url)
that.data.uploadImgList=that.data.uploadImgList.concat(imgPath_url)
console.log(that.data.uploadImgList)
that.setData({
uploadImgList:that.data.uploadImgList,
//uploadcurrent:current,
//imgList:'',
})
wx.showToast({
title: '上传数据成功',
icon: 'success',
duration: 500,
success: function () {
// setTimeout(() => {
// wx.navigateBack()
// }, 300)
}
})
if(that.data.uploadImgList.length==imgListData.length)//检测是否所有图片都上传完了
{console.log("开始回调");
resolve(that.data.uploadImgList);}
},
fail: function (res) {
console.log('接口调用失败');
console.log(res);
reject(res);
}
})
}
})
},
要注意的是,resolve()不能直接在success function中直接发生,因为我们在这里使用for循环来一张一张图片上传,若不设置一个结束条件,那么在第一张图片上传成功,success方法调用时,就会直接resolve,导致下一步(表单上传)不等所有图片上传完就开始。
submit方法的修改(部分代码),注意async和await的搭配使用:
formSubmit:async function(e){//在function前添加async
if (e.detail.value.shopposition == '') {
wx.showModal({
title: '提示',
content: '地址不能为空',
showCancel: false,
success: function (res) {
}
})
}
else {
console.log('form发生了submit事件,携带数据为:', e.detail.value);
var that=this;
var shoptoken=that.data.token;
console.log(shoptoken);
if(that.data.imgList!=''&&that.data.imgList!=null)//注意先判断图片地址是否为空
{await this.uploadimagFile();} //使用await
console.log(that.data.uploadImgList);
wx.request({
//省略
})
}
},
版权声明:本文为weixin_43616676原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。