H5使用微信JSSDK的wx.chooseImage进行多文件上传

news2024/12/23 17:32:51

背景:项目需要用H5做一个上传多图片合成的功能页面,这里我先做了调查,调查结果是安卓在微信内核不能使用传统的input file进行多文件上传,只能限制每次上传一张,ios则不限制,所以H5想在微信内核进行多图片上传就采用微信JSSDK进行功能实现多图片上传

 大概的思路逻辑是这样的:

1.引用jssdk的api即wx.chooseImage进行多图片上,上传得到的“localIds”安卓可以直接作为img标签显示,ios要通过wx.getLocalImgData传入“localIds”得到base64图片直接在本地显示

2.通过wx.chooseImage上传得到的“locallds"再调用wx.uploadImage得到serverId,然后再把serverId给到后台就可以拿到图片文件了

这里先记录一下这个项目踩过的坑,望周知

1.前端开发这里后台需要我拿到用户上传的照片的文件流,我查看了文档起初没有看到哪个方法可以拿到文件流,查看了一下资料看到了另外一个方法就是通过 wx.getLocalImgData前端可以拿到base64,然后再转成文件流给到后台同学,具体代码如下:

//先通过微信jssdk的api拿到了base64
wxgetLocalImgData(localIds) {
      let _this = this
      var i = 0
      var length = localIds.length
      var upload = function () {
        wx.getLocalImgData({
          localId: localIds[i], // 图片的localID
          success: function (res) {
            let localData = res.localData // localData是图片的base64数据,可以用img标签显示
            localData = localData.replace('jgp', 'jpeg')
            if (localData.indexOf('data:image') != 0) {
              //判断是否有这样的头部,因为安卓返回的是没有带头部的,所以要判断给它加上
              localData = 'data:image/jpeg;base64,' + localData
            }
            localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg') // 此处的localData 就是你所需要的base64 
              _this.localIdImgs.push(localData)
            if (_this.localIdImgs.length >= length) {
              alert('_this.localIdImgs.length+' + _this.localIdImgs.length)
                _this.getBase(_this.localIdImgs) //这里就可以拿到所有的base64传给逻辑函数了
              }
            i++  //因为多图片上传采用了这个方法
            i < length && upload()
          }
        })
      }
      upload()
    },

/* 微信sdk上传图片获取base64的处理逻辑 */
    getBase(base) {
      let _this = this
      var formData = new FormData()
      const photoName = `${new Date().getTime()}`
      base.forEach(element => {
        let initData = element.replace(/%0A|\s/g, '')
      //这里的base64ToFile就是base64转文件流的方法
        let p = _this.base64ToFile(initData, `${photoName}.jpg`)  
        formData.append('file', p)
      })
     //这个是后台的上传接口,前端把用户上传的文件流给到后台同学
      uploadImageFile(formData)
        .then(res => {
          console.log('res', res)
          alert('有进请求接口')
          if (res.code == '0000' && res.data) {
            console.log('上传成功了呢')
          } else {
            _this.$toast('上传失败')
          }
        })
        .catch(e => {
        
          alert('报错')
        })
    },

  /* base64转文件流方法 */
    base64ToFile(urlData, fileName) {
      let myPromise2 = new Promise((resolve, reject) => {
        let arr = urlData.split(',')
        let mime = arr[0].match(/:(.*?);/)[1]
        let bytes = atob(arr[1]) // 解码base64
        let n = bytes.length
        let ia = new Uint8Array(n)
        while (n--) {
          ia[n] = bytes.charCodeAt(n)
        }
        let files = new File([ia], fileName, { type: mime })
        // return new File([ia], fileName, { type: mime })
        resolve(files)
      })

      myPromise2.then(res => {
        alert('转换成功')
        return res
      })
      myPromise2.catch(err => {
        alert('请重新选择图片')
        reject('err')
      })
    },

 

2.这里一切都以为可以把用户上传的文件流给到后台接口同学了,但是经测试噩耗出现了,我在手机页面打印了每次请求到的base64,安卓和ios都打印出来在页面span标签显示(因为console打印本地调试看不到,微信的jssdk测试每次只能在https环境下测试,也就是线上地址,这我很烦!)测试发现安卓图片像素2M以下的图片转成的base64都可以正常在页面回显,也可以正常的转为文件流,但是大于2M的图片,页面的Img标签不显示了,把base64拷贝去工具转图片也发现图片是裂开的,显示不了,网上资料说图片像素越清晰返回的base64压缩的越严重导致图片打不开,文件流也转不了,ios还正常点,好像是10M以内可以回显和转换,所以到这里就打消了我原来用用户上传的base64转成文件流给到后端的方法了,只能改用另外一种方案,请听我细讲:

现在我急切的就是想拿到用户上传的文件流,又去看了一下官方文档,如下:

前端可以拿到这个media_id给后台接口,这里我要说明一下这里的意思:

它的备注写了可以用微信多媒体接口,这里的多媒体接口就是“获取临时素材”接口的意思

https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID1.前端可以通过这个接口get请求就可以直接拿到用户上传的文件流地址了,这里需要上传两个参数,一个是access_token,这个token一般是后台鉴权的令牌,可以找到后台同学拿,第二个media_id,就是上面wx.uploadImage拿到的serverId即media_id

2.上面是通过前端直接请求得到文件地址,但是access_token一般由后台保管不传给前端,这会后台可以封装https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID 这个接口,然后重新写个接口给前端,前端只需要每次把用户上传的serverId给到后台接口就可以了

好了,入坑的废话有点多了,接下来下面贴一下我正确请求的一个思路

=========================================================================

 

<template>
  <div>
    <button @click="onClickUp">测试</button>
   
  </div>
</template>
import wx from 'jweixin-1.6.0'  //引用微信sdk
import base from '@/utils/base.js'
import { getConfig } from '@/api/home'
export default {
  data() {
    return {
      kk: [],
      localIdImgs: [],
      localData: [],
      serverId: [],

    }
methods: {

getUrlconfig() {
      const browser = base.browser()  //这个方法就是判断是否是微信内核流浪器的,你们可以自己写一个方法判断
      // 微信分享提示
      if (browser.weixin || browser.qq || browser.yixin) {
        let signLink = ''
        let linkStatu = this.isIosOrAndroid() //判断安卓还是ios

        if (linkStatu === 'android') {
          signLink = location.href.split('#')[0]
        } else {
          signLink = window.initUrl
        }
        //请求微信sdk的当前页面url
        let params = {}
        params.url = signLink
        //请求微信sdk
        this.wxChatShare(params) //这个方法就是请求微信配置的,直接把参数带过就可以了
        return
      }
    },

wxChatShare(param) {
      //这里的param参数在需要的页面写好,然后代入到这里来就可以了
      // let _url = encodeURIComponent(param.url) // 当前页面的url
      let _url = param.url // 当前页面的url
      let data = {}
      data.sUrl = _url
      getConfig(data) // getConfig是获取微信配置相关信息的接口,此处根据个人项目写法而定
        .then(res => {
          if (res.code === '0000' && res.data) {
            console.log('res请求成功config', res)
            // alert('成功')
            let list = res.data
            let self = this
            // 接口返回配置信息
            wx.config({
              debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
              appId: 'wx0******ea5', // 必填,公众号的唯一标识
              timestamp: list.timeStamp, // 必填,生成签名的时间戳
              nonceStr: list.nonceStr, // 必填,生成签名的随机串
              signature: list.signature, // 必填,签名
              jsApiList: [
                // 用的方法都要加进来
                'chooseImage',
                'uploadImage',
                'downloadImage',
                'getLocalImgData'
              ]
            })
            wx.checkJsApi({
              jsApiList: ['chooseImage', 'uploadImage', 'downloadImage', 'getLocalImgData'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
              success: function (res) {
                // 以键值对的形式返回,可用的api值true,不可用为false
                // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
                console.log('检查', res)
                // alert(res.errMsg)
              }
            })
            wx.ready(function () {
         
            })
            wx.error(function (res) {
              console.log('验证失败返回的信息:', res)
            })
          } else {
            console.log('错误', res)
          }
        })
    },

     onClickUp() {
      let _this = this
      wx.chooseImage({
        count: 9, // 默认9
        sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
        success: function (res) {
          let localIds = res.localIds // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
          // 判断 ios
          const browser = base.browser()
          let linkStatu = _this.isIosOrAndroid() //判断安卓还是ios

          _this.wxuploadImage(localIds)

        },
        fail: function (res) {
          console.log('失败')
        }
      })
    },
    
wxuploadImage(localIds) {
      let _this = this
      var i = 0
      var length = localIds.length
      var upload = function () {
        let loacId = localIds[i]
        let linkStatu = _this.isIosOrAndroid() //判断安卓还是ios
        if (!(linkStatu == 'android')) {
          if (loacId.indexOf('wxlocalresource') != -1) {
            loacId = loacId.replace('wxlocalresource', 'wxLocalResource')
          }
        }
        wx.uploadImage({
          localId: loacId, // 需要上传的图片的本地ID,由chooseImage接口获得
          isShowProgressTips: 1, // 默认为1,显示进度提示
          success: function (res) {
            _this.serverId.push(res.serverId)  //这里就可以拿到用户上传的所有图片serverId
             if (_this.serverId.length >= length) {
                alert('_this.serverId.length+' + _this.serverId.length)
                _this.sendMediaid(_this.serverId)   //这个方法就是可以把拿到的服务id给到后台接口拿图片文件
              }
            i++
            i < length && upload()
          },
          fail: function (error) {}
        })
      }
      upload()
    },
    
/* 微信sdk拿到图片服务id给后台接口 */
    sendMediaid(serverId) {
      alert("id++" + serverId) // 如果多图片上传,这里是一个数组里面包含多个服务id,看后台想怎么处理把服务id给到后台同学
      let data = {
        mediaId:serverId
      }
   //把服务id给到后台接口
      uploadImageFile(data)  
        .then(res => {
          console.log('res', res)
          alert('有进请求接口')
          if (res.code == '0000' && res.data) {
            console.log('上传成功了呢')
           
          } else {
         
             console.log('上传失败')
          }
        })
        .catch(e => {
        
          alert('报错')
        })
    },
    

  }
  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/358319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实验室三维磁场电磁铁的主要用途及技术指标

产品用途&#xff1a; 北京锦正茂科技有限公司自主研发的多极电磁铁以四极电磁铁居多&#xff0c;也有五极、六极、八极等多极的应用&#xff0c;主要应用于磁滞现象研究、磁化系数测量、霍尔效应研究、磁光实验、磁场退火、核磁共振、电子顺磁共振、生物学研究、磁性测量、磁性…

实力见“证”:Tapdata 技术创新与发展潜力广受认可

Tapdata 积极拥抱各种“不确定”&#xff0c;变中求新&#xff0c;只为呈现出更加好用的产品。 而 Tapdata 在专业领域不断深耕&#xff0c;持续打磨产品能力的同时&#xff0c;也收获了诸多来自外界的肯定&#xff0c;从用户到投资人&#xff0c;从生态伙伴到技术媒体以及官方…

【Mysql系列】Mysql之窗口函数

适用场景 窗口函数适用场景: 对分组统计结果中的每一条记录进行计算的场景下, 使用窗口函数更好, 注意, 是每一条&#xff1b;因为MySQL的普通聚合函数的结果(如 group by)是每一组只有一条记录。 准备数据 创建表 create table app_product (id bigint auto_in…

4次迭代,让我的 Client 优化 100倍!泄漏一个 人人可用的极品方案!

4次迭代&#xff0c;让我的HttpClient提速100倍 在大家的生产项目中&#xff0c;经常需要通过Client组件&#xff08;HttpClient/OkHttp/JDK Connection)调用第三方接口。 尼恩的一个生产项目也不例外。 在一个高并发的中台生产项目中。有一个比较特殊的请求&#xff0c;一次…

「文档数据库之争」MongoDB和CouchDB的比较

MongoDB和CouchDB都是基于文档的NoSQL数据库类型。文档数据库又称mdocument store&#xff0c;通常用于存储半结构化数据的文档格式及其详细描述。它允许创建和更新程序&#xff0c;而不需要引用主模式。移动应用程序中的内容管理和数据处理是可以应用文档存储的两个字段。Mong…

积分球原理及积分球类型介绍

标题积分球标准型积分球LED积分球均匀光源便携式高亮度积分球均匀光源微光积分球均匀光源积分球均匀光源iSphere高光谱响应光学积分球其他分类积分球 积分球原理:由于球体内整涂有白色漫反射材料的空腔球体&#xff0c;球壁上开有采样口&#xff0c;当待测样品光源进入积分球的…

Java之关于String字符串笔试面试重点

目录 一.关于字符串的常量池 1.关于字符串产生的三种方式 2.关于字符串的常量池 3.直接赋值法和new的方式产生对象的区别 二.关于intern方法 1.情况一(已经包含) 2.情况二(已经包含) 3.情况三(未包含) 4.情况四 三.关于字符串的不可变性 1.了解字符串的不可变性 2.Str…

python+selenium使用webdriver启动chrome出现闪退现象解决

这两天发现之前开发的爬虫程序出问题了&#xff1a;谷歌浏览器出现打开立即闪退的现象&#xff0c;代码未修改过&#xff0c;检查也没有任何问题&#xff01; 查看chrome浏览器发现版本更新了 ↑&#xff08;点击chrome浏览器右上角三个点&#xff0c;最下面帮助→Google Chr…

[软件工程导论(第六版)]第9章 面向对象方法学引论(课后习题详解)

文章目录1. 什么是面向对象方法学&#xff1f;它有哪些优点&#xff1f;2. 什么是“对象”&#xff1f;它与传统的数据有何异同&#xff1f;3. 什么是“类”&#xff1f;4. 什么是“继承”&#xff1f;5. 什么是模型&#xff1f;开发软件为何要建模&#xff1f;6. 什么是对象模…

[软件工程导论(第六版)]第8章 维护(复习笔记)

文章目录8.1 软件维护的定义8.2 软件维护的特点8.3 软件维护过程8.4 软件的可维护性8.5 预防性维护8.6 软件再工程过程维护的基本任务&#xff1a;保证软件在一个相当长的时期能够正常运行软件工程的主要目的就是要提高软件的可维护性&#xff0c;减少软件维护所需要的工作量&a…

C语言编程规范 第一部分

、代码总体原则 1、清晰第一 清晰性是易于维护、易于重构的程序必需具备的特征。代码首先是给人读的&#xff0c;好的代码应当可以像文章一样发声朗诵出来。目前软件维护期成本占整个生命周期成本的40%~90%。根据业界经验&#xff0c;维护期变更代码的成本&#xff0c;小型系统…

Spring Batch ItemProcessor组件-默认处理器

目录 引言 概念 默认ItemProcessor ValidatingItemProcessor&#xff1a;校验处理器 ItemProcessorAdapter&#xff1a;适配器处理器 ScriptItemProcessor&#xff1a;脚本处理器 CompositeItemProcessor&#xff1a;组合处理器 自定义ItemProcessor处理器 转视频版 引…

图数据库中的 OLTP 与 OLAP 融合实践

在一些图计算的场景下&#xff0c;我们会遇到同时需要处理 OLTP 和 OLAP 的问题。而本文就给了一个 OLTP 与 OLAP 融合实践的指导思路&#xff0c;希望给你带来一点启发。 Dag Controller 介绍 Dag Controller 是 NebulaGraph 企业版的图系统&#xff0c;经过反复测试无误后已…

rabbitMq安装(小短文)--未完成

rabbitMq是在activeMq的基础上创造的&#xff0c;有前者的功能&#xff0c;比前者强&#xff0c;属于后来居上。系统环境:windows10首先下载相关软件Erlang&#xff0c;因为他是这个语言写的。https://www.erlang.org/downloads然后安装&#xff0c;并且弄到环境变量里验证是否…

Robot Framework自动化测试---元素定位

不要误认为Robot framework 只是个web UI测试工具&#xff0c;更正确的理解Robot framework是个测试框架&#xff0c;之所以可以拿来做web UI层的自动化是国为我们加入了selenium2的API。比如笔者所处工作中&#xff0c;更多的是拿Robot framework来做数据库的接口测试&#xf…

Leetcode.2257 统计网格图中没有被保卫的格子数

题目链接 Leetcode.2257 统计网格图中没有被保卫的格子数 Rating &#xff1a; 1709 题目描述 给你两个整数 m和 n表示一个下标从 0开始的 m x n网格图。同时给你两个二维整数数组 guards和 walls&#xff0c;其中 guards[i] [rowi, coli]且 walls[j] [rowj, colj]&#xff…

适合初学者的超详细实用调试技巧(下)

我们日常写代码的时候&#xff0c;常常会遇到bug的情况&#xff0c;这个时候像我这样的初学者就会像无头苍蝇一样这里改改那里删删&#xff0c;调试的重要性也就显现出来&#xff0c;这篇文章接着上文来讲解。 上文地址&#xff1a;(8条消息) 适合初学者的超详细实用调试技巧&…

Tomcat目录介绍,结构目录有哪些?哪些常用?

bin 启动&#xff0c;关闭和其他脚本。这些 .sh文件&#xff08;对于Unix系统&#xff09;是这些.bat文件的功能副本&#xff08;对于Windows系统&#xff09;。由于Win32命令行缺少某些功能&#xff0c;因此此处包含一些其他文件。 比如说&#xff1a;windows下启动tomcat用的…

3款强大到离谱的电脑软件,个个提效神器,从此远离加班

推荐3款让你偷懒&#xff0c;让你上头的提效电脑软件&#xff0c;个个功能强大&#xff0c;让你远离加班&#xff01; 很多几个小时才能做好的事情&#xff0c;用上它们&#xff0c;只需要5分钟就行&#xff01;&#xff01; 1、JNPF —— 个人最喜欢的低代码软件 它为开发者…

利用OpenCV的函数equalizeHist()对图像作直方图均衡化处理

如果一幅图像的灰度值集中在某个比较窄的区域&#xff0c;则图像的对比度会显得比较小&#xff0c;不便于对图像的分析和处理。 图像的直方图均衡化可以实现将原图像的灰度值范围扩大&#xff0c;这样图像的对比度就得到了提高&#xff0c;从而方便对图像进行后续的分析和处理…