最近在做小程序的时候,做了一个对服务区满意度评价的功能,需要上传一张或多张图片作为评价依据。但是介于微信选择图片后无需上传即可看到预览图,所以我不打算在用户一选择图片后就及时上传,而是在提交评论时再统一上传选好的图片,这样做的原因,是考虑到用户选好图片后存在删除图片的情况,如果一选择就上传,后面提交时又删除了该图片,就浪费了流量,毕竟现在一张手机照的图片,动不动就几兆,看文章都可以看好多好多篇了,能节约的就节约。
下面说一下重点,就是在提交评论时,存在多张图片的可能,但我们必须要保证所有图片都上传成功了才发送评论的请求。问题在于,小程序的wx.uploadFile每次只能上传一个文件,要上传多个,只能使用for循环,但如果用for循环,如何知道所有的上传都成功了,是个很棘手的问题。好在小程序里面可以使用promise,所以自然而然的就想到了promise.all方法。但直接把wx.uploadFile放到promise.all里面,是行不通的,因为他不具有promise.all所必须的then属性,所以我们做的事情,大致分以下几步:
一、是先封装wx.uploadFile。实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// wxUploadFile.js module.exports = function(option){ return new Promise((resolve, reject) => { option.name = 'file' option.success = function (res) { let data = JSON.parse(res.data) // 特别注意,这里要用JSON.parse对data进行转换 if (data.code === 0){ // 上传成功的判断,根据后端的返回自己处理 resolve(data.data) }else{ reject(res) } } option.fail = function (res) { reject(res) } wx.uploadFile(option) }) } |
二、在需要的页面引入
1 2 3 4 5 6 7 8 9 10 11 12 |
const wxUploadFile = require('../../js/wxUploadFile.js') // 如果是上传一个文件,就可以像下面这样使用了 wxUploadFile({ url:app.globalData.fileUploadUrl, filePath: res.tempFilePaths[0], header:{ 'Content-Type': 'multipart/form-data' } }).then(res=>{ console.log(res) }) |
三、选择图片时,先不要上传,把选好的图片用变量存起来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
chooseImage(e) { // 最好是在一开始判断一下已经选择的文件是否达到上限,此处省略 // ... wx.chooseImage({ sizeType: ['original'], //['original', 'compressed']可选择原图或压缩后的图片 sourceType: ['album','camera'], //['album', 'camera']可选择性开放访问相册、相机 success: res => { const images = this.data.images.concat(res.tempFilePaths) // 限制最多只能留下3张照片,根据自己的需求修改 this.data.images = images.length <= 3 ? images : images.slice(0, 3) // $digest(this) this.setData({ images: images }) } }) } |
四、最后提交评价时先上传所有图片,再提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
// 提交 submitForm() { wx.showLoading({ title: '正在提交...', mask: true }) let commonentData = { // ...你的其他评价字段 } let _this = this if (this.data.images.length){ // 判断是否有图片 // 将选择的图片组成一个Promise数组,准备进行并行上传 const fileUpLoadArr = this.data.images.map(path => { return wxUploadFile({ url: app.globalData.fileUploadUrl, filePath: path, header: { 'Content-Type': 'multipart/form-data' } }) }) // 开始并行上传图片 Promise.all(fileUpLoadArr).then(res => { // 上传成功,获取这些图片在服务器上的地址,组成一个数组 return res.map(item => { return { picFile: item.filePath } }) }).catch(err => { wx.hideLoading() _this.showError('图片上传出错,保存失败') }).then(data => { commonentData.appraisePicList = data _this.submitRequest(commonentData) //真正提交评价的地方 }) }else{ commonentData.appraisePicList = [] _this.submitRequest(commonentData) //真正提交评价的地方 } } |
好了,整个功能到此全部完成,特别需要注意的是,wx.uploadFile返回的数据需要格式化。还有一点可以优化的地方可以留给大家思考如何做,如果因为其他原因提交失败,再次提交时,文件其实已经上传过了,如何避免再次上传?
发表评论