评论

[开盖即食]利用“云函数”生成小程序码和将buffer流转化图片

云函数生成小程序码和buffer流转成图片的方法很多,简单分析了下哪些比较好

为什么要用云函数来做这个?

  • 前端一条龙不求人(后端)
  • 利用官方资源来快速解决问题,白piao不香吗?

之前也有不少人分享过云函数生成小程序码的方法,这里我为大家总结下不同方法的区别和优缺点~

开盖食用思路:

小程序端请求 --> 云函数API小程序 --> 返回图片的buffer --> 把buffer转化成图片

1、云函数部分

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
  try {
    const result = await cloud.openapi.wxacode.get({
      path: event.url, //传入需要配置的url,但是新版本不能传参param
      width: 300
    })
    console.log(result)
    return result
  } catch (err) {
    console.log(err)
    return err
  }
}

新建一个云函数名字为getWxacode,示例是openapi.wxacode.get的方法,这个参数可以直接跳转小程序内部对应的page。

注意:

与 wxacode.createQRCode 总共生成的码数量限制为 100,000,如果你需要大量生成码,请谨慎调用。且新版本只能传path,不能传参param~

2、页面部分

Page({
    data: {
        imgUrl: "" //图片地址
    },
    getWxacode() {
        wx.cloud.init();
        let self = this;
        wx.showLoading({
            title: '请求云函数'
        })
        // 调用云函数 获取 内容
        wx.cloud.callFunction({
            name: 'getWxacode',
            data: {
                url: "pages/home/index"
            },
            success: res => {
                console.log('云函数调用成功', res);
                let bufferImg = "data:image/png;base64," + wx.arrayBufferToBase64(res.result.buffer);
                self.setData({
                    //imgUrl: res.result.fileID
                    imgUrl: bufferImg
                });
                wx.hideLoading();
            },
            fail: err => {
                console.error('云函数调用失败', err)
            }
        })
    }
})


可以获得一个返回值,里面有个图片的buffer,转化buffer即可展示图片内容。

3、转化buffer流成图片的三种方法

3.1 直接将buffer转化Base64

console.log('云函数调用成功返回值:', res);
let bufferImg = "data:image/png;base64," + wx.arrayBufferToBase64(res.result.buffer);
self.setData({
    imgUrl: bufferImg
});

这里用到的方法是 wx.arrayBufferToBase64(buffer)转化,加好base64头,即可食用~

  • 优点: 方便简单
  • 确定: 阅后即焚,无法保存,个别场景可能需要缓存或者拼接canvas海报

3.2 在云函数直接将Buffer上传到云存储

await cloud.uploadFile({
    cloudPath: 'test/' + event.userInfo.openId  + '.jpg', //这里如果可以重复就用openId,如果不可能重复就用 
    fileContent: result.buffer, //处理buffer 二进制数据
    success: res => {
        // 文件地址
        console.log(res.fileID)
    },
    fail: err =>{
        console.log(err)
    }
})


将生成的小程序码上传到自带的云存储上,可以长期永久保存

  • 优点: 长期保存,合适只要生成一次反复使用的场景
  • 缺点: 生成量大的话,比较占用有限云存储资源

3.3 将图片转化保存在手机本地

let { buffer } = res.result;
const wxFile = wx.getFileSystemManager();
const filePath = wx.env.USER_DATA_PATH + '/test.jpg';
//把图片写在本地
wxFile.writeFile({
    filePath,
    encoding: "binary",
    data: buffer,
    success: res => {
        console.log(res);  //writeFile:ok
        self.setData({
            imgUrl: filePath
        });
    }
})

这里用到的是wx.getFileSystemManager()的方法,将图片buffer转化后保存一个本地地址~

  • 优点: 生成实体地址,有时候图片太大,base64会出现一些诡异的BUG
  • 缺点: 耗时

4、最终方案

经过综合考虑,这里使用的是不限次数的 openapi.wxacode.getUnlimited方法。

云函数部分:

const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
  try {
    const result = await cloud.openapi.wxacode.getUnlimited({
      scene: event.scene
    });
    console.log(result)
    return await cloud.uploadFile({
      cloudPath: 'test/' + event.userInfo.openId + '.jpg',
      fileContent: result.buffer, //处理buffer 二进制数据
      success: res => {
        // 文件地址
        console.log(res.fileID)
      },
      fail: console.error
    })
  } catch (err) {
    console.log(err)
    return err
  }
}

页面代码:

Page({
    data: {
        imgUrl: "" //图片地址
    },
    getWxacode() {
        wx.cloud.init();
        let self = this;
        wx.showLoading({
            title: '请求云函数'
        })
        // 调用云函数 获取 内容
        wx.cloud.callFunction({
            name: 'getWxacode',
            data: {
                scene: "goTo:pages/home/index"
            },
            success: res => {
                console.log('云函数调用成功', res);
                self.setData({
                    imgUrl: res.result.fileID
                });
                wx.hideLoading();
            },
            fail: err => {
                console.error('云函数调用失败', err)
            }
        })
    },
})

5、注意事项

5.1 生成码一共有三种方法:

  1. openapi.wxacode.get 小程序码,可以直接生成path,但不能传参,有次数限制
  2. openapi.wxacode.createQRCode 二维码,有次数限制
  3. openapi.wxacode.getUnlimited 特定scene传参,无次数限制 (推荐使用)

1和2方法累积10w次限制

5.2 代码报错,跑不了等


记得初始化 wx.cloud.init();


记得部署云函数~ ctrl+s 是没用的~~~

记得先本地调试好,再上传~~~

官方文档地址:
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.get.html

看完觉得有帮助记得点个赞哦~

你的赞是我继续分享的最大动力!^-^

最后一次编辑于  2021-09-13  
点赞 17
收藏
评论

7 个评论

  • 再瘦十斤
    再瘦十斤
    10-23

    大佬威武

    10-23
    赞同
    回复
  • 朱高
    朱高
    2022-07-20

    楼主有没试过 isHyaline 这个参数?生成不了透明的小程序码

    2022-07-20
    赞同
    回复
  • Wu
    Wu
    2022-04-02

    主要是忍不住想评论下那句 “前端一条龙不求人(后端)”,NB




    2022-04-02
    赞同
    回复
  • 光军
    光军
    2021-10-24

    学习了

    2021-10-24
    赞同
    回复
  • yunran
    yunran
    2021-10-08

    收藏了

    2021-10-08
    赞同
    回复
  • Archimedes👹(๑•̀ㅂ•́)و✧
    Archimedes👹(๑•̀ㅂ•́)و✧
    2021-01-10

    第三种方法writefile的时候 总报错{errMsg: "writeFile:fail atob is not defined"}怎么办啊

    2021-01-10
    赞同
    回复
  • 郑旭东
    郑旭东
    2020-11-14

    请教下,通过转base64直接显示到image组件后,如何再调用saveImageToPhotosAlbum下载图片?也就是如何拿到这张图的临时文件地址?或者有其他实现思路呢?

    2020-11-14
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-11-19
      据我了解“在不借助外部API的情况下”,不能直接将base64保存在本地相册,但是一般会通过后台接口,或者云函数把base64转化流保存。 或者让用户长按保存
      2020-11-19
      回复
登录 后发表内容