微信公众号开发-jssdk调微信chooseImage保存到七牛云

140 阅读2分钟

需求背景

公司所有的上传图片都很慢,原因是先把图片资源上传到公司服务器然后转存七牛云,公司服务器性能一般导致的。
h5页面要兼容微信客户端跟普通浏览器多图上传功能

解决方案

服务端提供七牛云上传token,前端直连七牛云省去了转存过程。
upload-token
七牛云直传文件
uniapp.uploadFile方法

实现

  • 非微信客户端浏览器可直接调用uniapp中chooseImage方法
问题:浏览器中无法控制选择的数量,虽然选择后返回结果是指定数量,但是界面选择时可以任意选择  

new Promise((resolve, reject) => {
    uni.chooseImage({
      count, //默认9
      sizeType, //可以指定是原图还是压缩图,默认二者都有
      sourceType, //从相册选择
      success: function (res) {
        // res.tempFilePaths[0]这个url就是uniapp.uploadFile方法中的filePath参数
        // 示例:blob:http://192.168.1.121:5173/3662a774-8ee3-4be8-aa5e-9e3c18528e7d
        resolve(res)
      },
      fail: (error) => {
        reject(error)
      }
    });
 })
1. 先调chooseImage
2. 再把chooseImage返回的localIds使用getLocalImgData转成base64
3. 将base64文件转成二进制获取到blob对象,图片类型也可以拿到
4. 使用window.URL.createObjectURL(blob)方法转成url地址就可使用
   uniapp.uploadFile方法中filePath上传了,当然也可以使用file对象(仅支持H5)  
   
1. new Promise((resolve, reject) => {
    wx.chooseImage({
        count, // 默认9
        sizeType, // 可以指定是原图还是压缩图,默认二者都有
        sourceType, // 可以指定来源是相册还是相机,默认二者都有
        success: function (res) {
           resolve(res);
        },
        fail: (error) => {
           reject(error)
        }
    })
   })
 2. new Promise((resolve, reject) => {
        wx.getLocalImgData({
        localId, // 微信相册选择图片的localID
        success: function (res: any) {
            const localData = res.localData;
            let imageBase64 = '';
            if (localData.indexOf('data:image') === 0) {
                //苹果的直接赋值,默认生成'data:image/jpeg;base64,'的头部拼接
                imageBase64 = localData;
            } else {
               //此处是安卓中的唯一得坑!在拼接前需要对localData进行换行符的全局替换
               imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
            }
            resolve(imageBase64);
        },
        fail: (error: any) => {
            reject(error)
        }
      })
    })
  3. /**
    * base64转为可post的二进制数据
    */
    function dataURLtoBlob(dataurl) {
      let arr = dataurl.split(',');
      let mime = arr[0].match(/:(.*?);/)[1];
      let bstr = atob(arr[1]);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], {
        type: mime
      });
    }
  4. const blob = dataURLtoBlob(localData); // localData是getLocalImgData方法返回的本地图片数据
     const blobUrl = window.URL.createObjectURL(blob) || ''; // 转成bolb url地址
     这个blobUrl就是uniapp.uploadFile中filePath参数url
     // 示例:blob:http://192.168.1.121:5173/ae12feb2-965e-43dd-ab7f-d828a727ee73

直传七牛云 uniapp写法

const uploadTask = uni.uploadFile({
    url: 'https://upload.qiniup.com/', // 七牛云上传存储区域我用的是华东-浙江 加速上传
    filePath, // 图片本地地址url,blob:http://192.168.1.121:5173/ae12feb2-965e-43dd-ab7f-d828a727ee73
    name: 'file',
    formData, // {'token': '你的七牛云token', key: '设置图片名称key'}
    success: (res) => {
      try {
        if (res.statusCode !== 200) return reject(res);
        const dataString = res.data;
        const dataObject = JSON.parse(dataString);
        // 拼接fileURL 不管是qiniuShouldUseQiniuFileName true还是false 都需要拼接
        dataObject.imageUrl = `${你的七牛云地址域名}/${dataObject.key}`;// key是上传到七牛云时传的图片key
        // 生成图片示例{imageUrl: 'http://public.xxx.com/custcome/test/20230420165506_3528.jpg'}
          resolve(dataObject);
        } catch (e) {
          reject(e);
        }
      },
      fail: (error) => {
        reject(error);
      }
    })
    // 文件上传进度
    uploadTask.onProgressUpdate((res) => {
      progress && progress(res);
    })
    // 中断文件上传
    cancelTask && cancelTask(() => {
      uploadTask.abort();
    })
})

小结

附一个七牛云示例