第七章:小程序云开发-云存储、云函数

云存储

云存储介绍

  1. 云存储用于将文件存储到云端:
    1. 云存储提供高可用、高稳定、强安全的云端存储服务;
    2. 持任意数量和形式的非结构化数据存储,如视频和图片;
    3. 并在控制台进行可视化管理;
  2. 云存储常见的操作:
    1. 上传文件到云存储中(图片、视频、音频等等都可以)
    2. 获取文件的临时链接(在外网可以访问)
    3. 下载文件到本地(本地文件缓存)
    4. 将云存储中的文件删除

云存储操作

  1. 云开发三大核心之一的云存储
  2. 官方文档:开发->云开发->开发指引->存储

在控制台操作

  1. 打开云开发控制台->存储->上传文件,比如上传一个图片
  2. 文件上传后,会生成一个FileID,这个ID就相当于一个地址,但是只能用在小程序中,不能再浏览器打开

     <image src="cloud://coderzhong-dev-jp44t.636f-coderzhong-dev-jp44t-1302023490/ic_cat_music.png"></image>
    
  3. 点击这张图片的文件名称,就可以获取到这张图片的url地址,可以在浏览器打开了。

代码操作

  1. hstorage.wxml文件

     <!-- 1. 上传文件 -->
     <button bindtap="uploadFile">上传图片</button>
     <image wx:if="*{imageFileID}}" src="*{imageFileID}}"/>
     <button bindtap="uploadVideo">上传视频</button>
     <video wx:if="*{videoFileID}}" src="*{videoFileID}}"/>
     <!-- 2. 获取临时连接 -->
     <button bindtap="getTempURL">获取临时链接</button>
     <!-- 3. 下载资源 -->
     <button bindtap="downLoadVideoFile">下载视频文件</button>
     <video wx:if="*{localFilePath}}" src="*{localFilePath}}"/>
     <!-- 4. 删除资源 -->
     <button bindtap="deleteFile">删除文件</button>
    
  2. zhstorage.js文件

     Page({
       data:{
        
         imageFileID: "",
         videoFileID: "",
         localFilePath:""
       },
       /*****1.上传文件到云存储***** */
       // 上传图片
       uploadFile: function(){
         // 1. 用户选择一张图片(拍照、相册)
         // 文档->api->媒体->图片
         wx.chooseImage({
           success: (res)=> {
             console.log(res);
             // 2. 获取选中图片的路径
             const filepath = res.tempFilePaths[0];
             //3. 上传图片到云存储
             // 时间戳
             const timestamp = new Date().getTime();
             // 当前登录用户的唯一标识,微信小程序自带
             const openId = '11111';
             //上传到云存储的位置:路径+名称
             const fileName = `images/${timestamp}_${openId}.png`;
             wx.cloud.uploadFile({
               filePath: filepath,
               cloudPath: fileName,
             }).then(res=>{
               const fileID = res.fileID;
               console.log(fileID);
               this.setData({
                 imageFileID:fileID
               })
             })
           },
         })
       },
       // 上传视频
       uploadVideo: function(){
         // 文档->api->媒体->视频
         wx.chooseVideo({
           success:res=>{
             // 拿到上传后的路径
             const filepath = res.tempFilePath;
             wx.cloud.uploadFile({
               filePath: filepath,
               cloudPath: 'videos/123.mp4'
             }).then(res=>{
               const fileID = res.fileID;
               console.log(fileID);
               this.setData({
                 videoFileID: fileID
               })
             })
           }
         })
       },
       /*****2.上获取临时连接***** */
       getTempURL: function(){
         // 从云开发平台直接拷贝的fileID
         // 作用:如果云存储中某一个资源需要在小程序以外的地方访问时,就可以通过fileID换取外部可以访问的URL
         const fileID = 'cloud://coderzhong-dev-jp44t.636f-coderzhong-dev-jp44t-1302023490/images/1588852332741_11111.png';
         wx.cloud.getTempFileURL({
           fileList: [fileID]
         }).then(res=>{
           console.log(res.fileList[0].tempFileURL);
        
         })
       },
       /*****3.下载云存储的资源到本地***** */
       // 作用:资源缓存,没有网络也可以使用
       downLoadVideoFile:function(){
         wx.cloud.downloadFile({
           fileID:'cloud://coderzhong-dev-jp44t.636f-coderzhong-dev-jp44t-1302023490/videos/123.mp4',
         }).then(res=>{
           console.log(res.tempFilePath);
           this.setData({
             localFilePath: res.tempFilePath
           })
         })
       },
       /*****4.删除云存储的资源***** */
       deleteFile:function(){
         const fileID = 'cloud://coderzhong-dev-jp44t.636f-coderzhong-dev-jp44t-1302023490/videos/123.mp4';
         wx.cloud.deleteFile({
           // 传入fileID
           fileList: [fileID]
         }).then(res=>{
           console.log(res);
         })
       }
     })
    

云函数

云函数介绍

  1. 云函数即在云端(服务器端)运行的函数:
    1. 在物理设计上,一个云函数可由多个文件组成,占用一定量的 CPU 内存等计算资源;
    2. 各云函数完全独立;可分别部署在不同的地区;
    3. 开发者无需购买、搭建服务器,只需编写函数代码并部署到云端即可在小程序端调用;
    4. 同时云函数之间也可互相调用;
  2. 云函数的编写方式:
    1. 一个云函数的写法与一个在本地定义的 JavaScript 方法无异,代码运行在云端 Node.js 中;
    2. 当云函数被小程序端调用时,定义的代码会被放在 Node.js 运行环境中执行;
    3. 我们可以如在 Node.js 环境中使用 JavaScript 一样在云函数中进行网络请求等操作,而且我们还可以通过云函数后 端 SDK 搭配使用多种服务,比如使用云函数 SDK 中提供的数据库和存储 API 进行数据库和存储的操作
  3. 云开发的云函数的独特优势在于与微信登录鉴权的无缝整合。当小程序端调用云函数时,云函数的传入参数中会被注入小 程序端用户的 openid,开发者无需校验 openid 的正确性因为微信已经完成了这部分鉴权,开发者可以直接使用该 openid。

创建云函数

  1. 云开发项目都会有一个cloudfunctions文件夹,这个文件夹下默认有系统自带的云函数
  2. 默认这个文件夹“未指定环境”,因为我们可以有2个环境,右击可以选中一个环境
  3. 右击改文件夹->Node.js云函数->命名为“sum”
    1. 因为这个云函数是js代码,js代码通过Node.js在服务端运行
    2. 自动会生成一个文件夹,下面有一个js跟json文件
  4. 在sum.js文件中编写函数代码

     // 云函数入口文件
     const cloud = require('wx-server-sdk')
        
     cloud.init()
        
     // 云函数入口函数
     exports.main = async (event, context) => {
       return 20+30;
     }
    
  5. 右击sum文件夹->上传并部署…,只有上传成功才能调用云函数
  6. 调用云函数,在page的js代码中调用云函数

     //基本使用
     basicUsing: function(){
         // 如何调用云函数
         wx.cloud.callFunction({
           name:'sum'//调用哪一个云函数
         }).then(res=>{
           console.log(res);
         })
       }
     })
    

代码展示

注意点:

  1. 操作数据库时,对应云函数的js文件中初始化一定要指定环境,否则会报错,Db or Table not exist

     cloud.init({
       // 注意:!!!这里一定要指定环境,否则会报错,Db or Table not exist
       env: 'coderzhong-dev-jp44t',
       traceUser: true,
     })
    
  2. 获取access_token,自己写非常麻烦,可以通过npm获取第三方包wx-js-utils来实现
    1. npm是node包管理工具,npm里面有这个wx-js-utilsnode包,通过npm可以安装
    2. 由于npm执行依赖于node环境,因此当前pc需要安装node.js(安装方法百度)
    3. 安装完成后,打开终端,进入到需要安装wx-js-utils包的js文件目录(就是云函数列表)
    4. 执行命令: npm install wx-js-utils回车即可
    5. 安装完成后,就会发现该云函数的目录下,就会多一个packge-lock.json文件
    6. 同时,原来的packge.json文件内部依赖也会添加wx-js-utils

       "dependencies": {
           "wx-js-utils": "^1.0.0",
           "wx-server-sdk": "latest"
       }
      
  3. 为什么获取小程序码不通过小程序直接获取,却要使用云函数?
    1. 文档->服务端->小程序码
    2. 可以看到需要发送网络请求: https://api.weixin.qq.com....
    3. 因此需要将这个域名添加到小程序控制台,但是官方文档又指出:
      1. 出于安全考虑,api.weixin.qq.com 不能被配置为服务器域名,相关API也不能在小程序内调用....
      2. 所以,小程序不能直接发送https://api.weixin.qq.com...这个请求
    4. 因此只能通过当前公司的后台或者微信小程序云函数调用微信后台来完成
    5. 生成小程序码的逻辑:
      1. 通过appId和secret换取 access_token
        1. 通过官方文档获取麻烦,所以通过第三方来获取wx-js-utils
      2. 通过access_token请求小程序码
      3. 将小程序码上传到云存储中
      4. 将上传后的fileID返回给客户端 保存和显示

代码

  1. 页面搭建:zhcloudfunc.wxml文件

     <!-- 1. 云函数基本使用 -->
     <button bindtap="basicUsing">云函数的基本使用</button>
     <!-- 2. 通过云函数获取openId -->
     <button bindtap="getOpenID">获取openID</button>
     <!-- 3. 通过云函数删除多条数据 -->
     <!-- 云函数操作数据库权限更大 -->
     <button bindtap="removeMuData">删除多条数据</button>
     <!-- 4. 通过云调用生成小程序码 -->
     <button bindtap="generateCode">生成小程序码</button>
     <image src="*{fileID}}"/>
     <!-- 5. 发送模板消息:通过微信小程序,像微信发送模板消息 -->
     <!-- 指南-》开放能力-》消息-》模板消息(订阅消息)查看官方文档即可 -->
     <!-- 比如:用小程序付款成功,微信消息会有一条付款记录消息 -->
    
  2. 时间响应:zhcloudfunc.js

     Page({
       /**
        * 页面的初始数据
        */
       data: {
         fileID:''
       },
       //1. 基本使用
       basicUsing: function(){
         const num11 = 20;
         const num22 = 30;
         // 如何调用云函数
         wx.cloud.callFunction({
           name:'sum',//调用哪一个云函数
           data:{
             // 云函数传参
             num11,
             num22
           }
         }).then(res=>{
           console.log(res);
         })
       },
       //2. 获取openID
       /**
        * 1. 在cloudfunctions文件夹右击新建Node.js云函数->login
        * 2. login.js中的代码不用修改
        */
       getOpenID:function(){
         wx.cloud.callFunction({
           name:'login',
         }).then(res=>{
           console.log(res);
         })
       },
       // 3. 删除多条数据
       removeMuData:function(){
         wx.cloud.callFunction({
           name:'removeData'
         }).then(res=>{
           console.log(res);
         })
       },
       // 4. 获取小程序码
       generateCode:function(){
         wx.cloud.callFunction({
           name:'code'
         }).then(res=>{
           console.log(res.result.fileID)
           this.setData({
             fileID:res.result.fileID
           })
         })
       }
     })
    
  3. 上面的4个时间分布对应4个创建的云函数:

    1. sum云函数:index.js

       // 云函数入口文件
       const cloud = require('wx-server-sdk')
              
       cloud.init()
              
       // 云函数入口函数
       exports.main = async (event, context) => {
         // 注意外面传什么变量,这里接收什么变量num11、num22
         return event.num11+event.num22;
       }
      
    2. login云函数: index.js

       // 云函数入口文件
       const cloud = require('wx-server-sdk')
              
       cloud.init()
              
       // 云函数入口函数
       exports.main = async (event, context) => {
         const wxContext = cloud.getWXContext()
              
         return {
           event,
           openid: wxContext.OPENID,//当前用户在小程序的唯一标识
           appid: wxContext.APPID,//小程序的唯一标识
           unionid: wxContext.UNIONID,//不是任意小程序都能获取(可以标识出用户在多个微信平台使用微信登录)
         }
       }
      
    3. removeData云函数: index.js

       // 云函数入口文件
       const cloud = require('wx-server-sdk')
              
       cloud.init({
         // 注意:!!!这里一定要指定环境,否则会报错,Db or Table not exist
         env: 'coderzhong-dev-jp44t',
         traceUser: true,
       })
              
       // 云函数入口函数
       exports.main = async (event, context) => {
         // 1. 获取数据库对象
         const db = cloud.database();
        //2. 获取操作的集合
         const coll = db.collection("students");
         // return db;
       //  3. 根据条件删除数据
       const cmd = db.command;
       // 4. 直接返回promise就行
       return coll.where({
         age: cmd.gte(18)
       }).remove()
       }
      
    4. code云函数:index.js

       // 云函数入口文件
       const cloud = require('wx-server-sdk')
       // 需要通过npm安装wx-js-utils第三方依赖
       const {WXMINIUser,WXMINIQR} = require('wx-js-utils')
              
       // 注意:一定要设置环境,否则默认上传的就是第一次创建的环境
       cloud.init({
         // 注意:!!!这里一定要指定环境,否则会报错,Db or Table not exist
         env: 'coderzhong-dev-jp44t',
         traceUser: true,
       })
              
       // 云函数入口函数
       exports.main = async (event, context) => {
         // 需要通过nmp安装wx-js-utils第三方包,可以百度查看该第三方的使用
         // 如果直接通过文档,会比较麻烦: 文档->服务端->小程序码
         //1. 获取access_token
             const user = new WXMINIUser({
               // 这两个参数从微信公众平台管理端复制过来,登录微信公众平台-》开发-》开发设置
               appId: 'xxx',
               secret:'xxx'
             }); 
             // await将异步调用变成同步,getAccessToken是个异步函数
             const access_token = await user.getAccessToken();
             // return access_token;
         // 2. 获取小程序码
           const qr = new WXMINIQR();
         const qrCode = await qr.getMiniQRLimit({
             access_token: access_token,
             // 扫描小程序码进入小程序的那个页面
             path:'pages/index/index'
           })
         // 3. 将小程序码图片上传云存储中
         return cloud.uploadFile({
           cloudPath:'images/minicode.png',
           fileContent:qrCode
         })
              
       }
      
Table of Contents