微信多图上传 ios手机上偶尔出现报错chooseImage:the permission value is offline verifying

问题:微信多图上传 ios手机上偶尔出现报错chooseImage:the permission value is offline verifying(上传流程wx.chooseImage、给后台serverId用wx.uploadImage、本地展示用wx.getLocalImgData)

image.png

问题分析: 开启debug测试得出,先报错chooseImage:the permission value is offline verifying,在弹出config:ok

得出结论:导致错误的原因是"先执行了wx.chooseImage方法再执行wx.config(有请求异步导致)"。正常的情况是先弹出config,再调用wx.chooseImage方法

解决方法:

1、 setTimeout(() => { }, 400) // 延迟一下
2、放在wx.ready里面 确保wx.config执行完成触发

实现代码

Publish.vue

html
<!--图片展示-->
<div class="form-img-container" v-if="arr.length > 0">
  <!-- 微信上传图片 -->
  <wechat-uploader-img v-if="data" @addImg="addImg" @success="success(index)" @error="error(index)" :is-publish="true"   @showImgDetail="showImgDetail(index, data)"
                      v-for="(data,index) in arr" :key="index" :index="index" :info="data" :mold="'bulletin'"/>
</div>
<!--上传按钮-->
<template>
  <div class="uploaderImg" @click="handleChooseImage()">
    <div class="add-img-icon"></div>
    <div class="add-img-text">图片{{ arr.length }}/3张</div>
  </div>
</template>
js
// 微信上传
import WechatUploaderImg from '@/components/WechatUploaderImg'
export default {
  data () {
    return {
      form: {
        images: [] // 上传到服务器的相册
      },
      isLoading: false,
      // 暂存读取后数据
      arr: [],
      // 是否显示提示框
      showDialog: false,
      // 是否是ios手机
      isIos: this.$utils.isIOS()
    }
  },
  components: {
    WechatUploaderImg
  },
  methods: {
    // 图片上传(微信的js-dk)
    handleChooseImage () {
      if (this.isLoading) {
        return
      }
      this.isLoading = true

      let arr = []
      for (let i = 0; i < this.arr.length; i++) {
        if (this.arr[i]) {
          arr.push(this.arr[i])
        }
      }
      // 实际可用长度
      let arrLen = arr.length
      if (arrLen >= 3) {
        this.isLoading = false
        this.$utils.showMessage('亲,最多只能上传3张图片哦~')
      } else {
        if (this.isIos) {
          setTimeout(() => { // 解决问题的重要代码(定时器延时)
            this.fetChooseImage(arrLen)
          }, 400)
        } else {
          this.fetChooseImage(arrLen)
        }
      }
    },
    fetChooseImage (arrLen) {
      // eslint-disable-next-line
      wx.ready(() => { // 解决问题的重要代码(方wx.ready里面)
        this.$store.dispatch('Wechat/chooseImage', 3).then(res => {
          this.isLoading = false
          let localIds = res.localIds
          if (localIds.length > 0 && 3 - arrLen >= localIds.length) {
            this.localIdArr = localIds
          } else if (localIds.length > 0 && 3 - arrLen < localIds.length) {
            this.localIdArr = localIds.slice(0, 3 - arrLen)
          }
          this.handleUploadImage()
        }).catch(err => {
          this.isLoading = false
          if (err.errMsg !== 'chooseImage:cancel') {
            this.$utils.showErrorMsg('chooseImage:' + JSON.stringify(err))
          }
        })
      })
    },
    handleUploadImage () {
      if (!this.localIdArr.length) {
        return
      }
      let localId = this.localIdArr.shift()
      this.$store.dispatch('Wechat/uploadImage', localId).then(res => {
        let serverId = res.serverId // 返回图片的服务器端ID
        this.handleGetLocalImgData(localId, serverId)
        this.handleUploadImage()
      }).catch(err => {
        this.$utils.showErrorMsg(err)
      })
    },
    handleGetLocalImgData (localId, serverId) {
      this.$store.dispatch('Wechat/getLocalImgData', localId).then(res => {
        let localData = res.localData
        let obj = {
          // 读取成功的数据
          readData: localData,
          serverId: serverId,
          // 上传成功的状态 true代表成功,false代表还在上传,null代表错误
          isSuccess: false,
          // 是否显示蒙层
          isShow: true
        }
        this.arr.push(obj)
      }).catch(err => {
        this.$utils.showErrorMsg(err)
      })
    },
    // 数据库添加图片
    addImg (src, index) {
      if (index !== undefined && this.form.images.length > index) {
        this.form.images.splice(index, 1, {url: src})
      }
      if (index !== undefined && this.form.images.length <= index) {
        this.form.images[index] = {url: src}
      }
    },
    // 删除图片
    deleteImg () {
      this.arr.splice(this.imgDetailIndex, 1)
      this.form.images.splice(this.imgDetailIndex, 1)
      this.isShowImgDetail = false
    },
    // 上传成功的状态
    success (index) {
      this.arr[index].isShow = false
      this.arr[index].isSuccess = true
    },
    // 上传失败的提示
    error (index) {
      this.arr[index].isSuccess = null
    }
  },
  watch: {
    arr (newVal) {
      let length = newVal.length
      if (length === 0) {
        this.$refs.formInside.style.minHeight = '7.1rem'
        this.$refs.formMid.style.minHeight = '5.4rem'
      } else if (length > 0) {
        let trueLength = 0
        newVal.forEach(item => {
          if (item) {
            trueLength++
          }
        })
        if (trueLength > 0) {
          this.$refs.formInside.style.minHeight = 'unset'
          this.$refs.formMid.style.minHeight = '2.172rem'
        } else {
          this.$refs.formInside.style.minHeight = '7.1rem'
          this.$refs.formMid.style.minHeight = '5.4rem'
        }
      }
    }
  }
}

components/WechatUploaderImg

html
  <template v-if="mold == 'bulletin'">
      <div @click.prevent.stop="showImgDetail" v-if="info.readData" class="form-img">
        <!-- 公告预览 有http开头的图片 先判断http的图片再判断机型 -->
        <img v-if="info.readData.indexOf('http') === 0"  :src="info.readData" alt="">
        <img v-else-if="isIos" :src="info.readData" alt="">
        <img v-else :src="'data:image/gif;base64,' + info.readData" alt="">
        <transition name="fade">
          <div v-if="info.isShow" :id="index" class="img_circle"></div>
        </transition>
      </div>
  </template>

js

export default {
  created () {
    // 当url是http时不用上传
    if (this.info.readData && this.info.readData.indexOf('http') !== 0) {
      this.fetchImages()
    }
  },
  props: {
    info: {
      type: Object
    },
    index: {
      type: Number
    },
    mold: {
      type: String
    }
  },
  data () {
    return {
      loading: {
        rate: 0
      },
      // 是否是ios手机
      isIos: this.$utils.isIOS()
    }
  },
  methods: {
    // 图片上传到七牛
    fetchImages () {
      this.$http.post(`v1/common/upload/img`, {
        img_content: this.info.serverId,
        type: 1
      }).then(res => {
        let src = res.data.meta.img_url
        this.$emit('addImg', src, this.index)
        this.success()
      }).catch(err => {
        this.$utils.showErrorMsg(err)
        this.error()
      })
    },
    // 上传失败
    error () {
      this.$emit('error', this.index)
      this.$utils.showErrorMsg('图片上传有误,请重新上传')
    },
    // 上传成功
    success () {
      this.$emit('success', this.index)
    },
    // 删除
    splice () {
      this.$emit('splice', this.index)
    },
    // 点击预览
    showImgDetail () {
      this.$emit('showImgDetail', this.index)
    }
  },
  watch: {
    info (val) {
      // 微信上传
      if (this.mold === 'avatar' && this.info.readData && this.info.readData.indexOf('http') !== 0) {
        this.fetchImages()
      }
    }
  }
}

Wechat.js

import Http from '@/libs/Http'
import Utils from '@/libs/Utils'

const state = {
  url: ''
}

const mutations = {
  /**
   * 设置校验url
   * @param {Object} state 状态
   */
  setUrl (state) {
    let currentUrl = document.URL
    if (Utils.isIOS()) {
      let landingUrl = sessionStorage.getItem('ios_landing_url')
      if (landingUrl) {
        state.url = landingUrl
      } else {
        state.url = currentUrl
      }
    } else {
      state.url = currentUrl
    }
  }
}

const actions = {
  /**
   * 初始化微信配置
   * @param {*} param0
   * @param {*} payload payload.perms微信权限
   */
  initConfig ({commit, state}, payload) {
    return new Promise((resolve, reject) => {
      let data = {
        url: state.url,
        perms: payload.perms
      }
      Http.post('/v1/wechat/js', data).then(response => {
        let wechatJs = response.data.meta.wechat_js
        // wechatJs.debug = true
        /* eslint-disable no-undef */
        wx.config(wechatJs)
        resolve()
        wx.error(err => {
          console.log('wx.err', err)
        })
      }).catch(err => {
        Utils.showError(err)
        reject(err)
      })
    })
  },

  /**
   * 分享操作
   * @param {Object} param0
   * @param {Object} payload {title:'',link:null,desc:null,type:null,img:''}
   */
  share ({dispatch, state}, payload) {
    return new Promise((resolve, reject) => {
      dispatch('initConfig', {perms: ['onMenuShareTimeline', 'onMenuShareAppMessage']}).then(() => {
      // dispatch('initConfig', {perms: ['updateAppMessageShareData', 'updateTimelineShareData']}).then(() => {
        let parsedLink = payload.link === undefined || !payload.link ? window.location.href : payload.link
        /* eslint-disable no-undef */
        wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
          let share = {
            title: payload.title,
            link: parsedLink,
            desc: payload.desc,
            type: payload.type === null ? 'link' : payload.type,
            imgUrl: payload.img === undefined || !payload.img ? null : payload.img,
            success: resolve,
            cancel: reject
          }
          wx.onMenuShareTimeline(share)
          wx.onMenuShareAppMessage(share)
          // wx.updateAppMessageShareData(share)
          // wx.updateTimelineShareData(share)
        })
      })
    })
  },
  /**
   * 关闭分享操作
   */
  unShare ({dispatch, state}, payload) {
    return new Promise((resolve, reject) => {
      if (payload === 'both') {
        dispatch('initConfig', {perms: ['chooseImage', 'getLocalImgData', 'uploadImage', 'hideAllNonBaseMenuItem']}).then(() => {
          /* eslint-disable no-undef */
          wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
            wx.hideAllNonBaseMenuItem()
          })
        })
      } else {
        dispatch('initConfig', {perms: ['hideAllNonBaseMenuItem']}).then(() => {
          /* eslint-disable no-undef */
          wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
            wx.hideAllNonBaseMenuItem()
          })
        })
      }
    })
  },

  /**
   * 从相册中选图片或者拍照
   */
  chooseImage ({dispatch, state}, payload) {
    return new Promise((resolve, reject) => {
      // 因为是用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中
      wx.chooseImage({
        count: payload, // 默认9张照片
        sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
        success: resolve,
        fail: reject,
        complete: reject
      })
    })
  },

  /**
   * 获取本地图片
   */
  getLocalImgData ({dispatch, state}, payload) {
    return new Promise((resolve, reject) => {
      // 因为是用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中
      wx.getLocalImgData({
        localId: payload, // 图片的localID
        success: resolve,
        fail: reject
      })
    })
  },

  /**
   * 上传图片接口
   */
  uploadImage ({ dispatch, state }, payload) {
    return new Promise((resolve, reject) => {
      wx.uploadImage({
        localId: payload, // 需要上传的图片的本地ID,由chooseImage接口获得
        isShowProgressTips: 0, // 默认为1,显示进度提示
        success: resolve,
        fail: reject
      })
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 先引入JS 文件 this.wxShare() 在created里调用 首先登陆微信公众号 JSSDK使用步骤 步...
    寄鱼予海与你阅读 6,673评论 1 3
  • 1. 准备工作 1.1 查看公众号分享接口权限 要使用微信SDK必须要有经过微信认证的非个人服务号 登陆服务号后,...
    sxplus阅读 6,216评论 0 2
  • 微信公众号开发 ​前面做过 HG 项目的微信端,里面用到微信扫码、支付、图片选取、拍照、分享的功能。用到 weix...
    Ghnhxg阅读 524评论 1 1
  • 调用config 接口的时候传入参数 debug: true 可以开启debug模式,页面会alert出错误信息。...
    施主画个猿阅读 11,749评论 2 3
  • 世界与我 从此形同陌路 心禁了 或是最好结局 别再说委屈 别再说痛苦 干了这杯酒 把一切掩埋入土 就这样结束 我知...
    长缨书生阅读 544评论 0 0