小程序获取用户openid,并实现上传图片到python服务器

小程序实现上传图片到python服务器

预览

老规矩,先上demo。
额。。。。
忘了,这次情况特殊没有demo,看预览图吧:
小程序获取用户openid,并实现上传图片到python服务器_第1张图片
小程序获取用户openid,并实现上传图片到python服务器_第2张图片返回图片的网络地址

小程序前端

  • 获取用户信息,openId,用作生成用户专属图片文件夹

    • 要生成unionId,需要知道自己小程序appid,secert_key。可以登录微信开发平台进行查看。
    • wx.login 获取 code 从而得到用户信息:encryptedDataiv ,把这三个参数传给后台
    • code特别容易过期,所以需要使用wx.checkSession激活
    • python后台通过requests.get(https://api.weixin.qq.com/wxa/getpaidunionid?access_token=ACCESS_TOKEN&openid=OPENID
      )返回两个参数 session_keyappid
    • 通过从文档中下载的python服务端文件中的
      WXBizDataCrypt(appid, session_key)
      解密返回openId
    • 注意官方给出的解密包中有两处问题
      • WXBizDataCrypt中需要修改return decryptreturn jsonify(decrypted),把dict转为json
      • windows服务器上python无法下载Crpyto,别去网上找解决方法了,那些都是胡扯,直接pip install pycryptodome就OK了
  • wx.chooseImage 选择图片

    • 官方文档中有使用方法,我们只需配置一下参数就好
  • wx.uploadFile 上传图片

    • 验证是否有openId,携带openIdwx.chooseImage生成的图片路径传给服务器

小程序代码

app.js

App({
  onLaunch: function() {
    // 展示本地存储能力
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    let that = this
    wx.login({
      success: res => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        if (res.code) {
          wx.getUserInfo({
            success: e => {
              let info = {
                encryptedData: e.encryptedData,
                iv: e.iv,
                code: res.code
              }
              wx.request({
                url: 'https://xxxxxx.xx/api/v/userinfo',
                header: {
                  'content-type': 'application/x-www-form-urlencoded'
                },
                data: {
                  info: JSON.stringify(info) //把object转化为json数据
                },
                method: 'POST',
                success: function(u) {
                  const encryptedData = u.data
                  getApp().globalData.openid = encryptedData.openId
                },
                fail: function(f) {
                  console.log(f)
                },
              })
            },
            fail: function() {
              console.log('fail,login_fail')
            }
          })
        }
      }
    })
    wx.checkSession({
      success() {
        // session_key 未过期,并且在本生命周期一直有效
      },
      fail() {
        // session_key 已经失效,需要重新执行登录流程
        wx.login() // 重新登录
      }
    })
    // 获取用户信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          wx.getUserInfo({
            success: res => {
              // 可以将 res 发送给后台解码出 unionId
              this.globalData.userInfo = res.userInfo

              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },
  globalData: {
    userInfo: null,
    openid: ''
  }
})

index.js

const app = getApp()

Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
    src: '',
  },
  //事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function() {
    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
    } else if (this.data.canIUse) {
      // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
      // 所以此处加入 callback 以防止这种情况
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 在没有 open-type=getUserInfo 版本的兼容处理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },
  getUserInfo: function(e) {
    console.log(e)
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  },
  choose: function() {
    let that = this;
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'], //原图或压缩后
      sourceType: ['album', 'camera'], //相册,相机
      success: res => {
        const img = res.tempFilePaths
        that.setData({
          src: img
        })
      },
    })
  },
  upload: function() {
    const user = app.globalData.openid
    let that = this;
    let pic = that.data.src;
    wx.uploadFile({
      url: 'https://xxxx.xx/xxxx/xxx/xxxxxx/' + user,
      filePath: String(pic),
      name: 'test',
      success: function(e) {
        console.log(e)
      }
    })
  }
})

python 后台

  • 配置路由

  • 接受传过来的文件,及openId,hash加密后,创建文件夹

    • 创建create_folder函数,用来判断是否需要生成新的文件夹
    def creat_folder(folder_path):
     if not os.path.exists(folder_path):
         os.mkdir(folder_path)
         os.chmod(folder_path,os.O_RDWR)
    
    • 创建哈希加密函数md5,加密openid,以免暴漏真实id
       def md5(data):
     	md = hashlib.md5()
     	md.update(data.encode('utf-8'))
     	data = md.hexdigest()
     	return data
    
    • older_path接受参数os.path.join(app.config['UPLOADS_FOLDER'], md5(openId),
      生成独一无二的用户专属文件夹,用于存储用户上传的文件夹。
  • 使用pillow对图片进行存储

    • 重命名图片,可以使用日期时间+随机两位数进行命名
    • 进行操作,如(加滤镜,加水印,裁剪压缩等)
    • 储存
  • 返回图片的网络地址

    • img_dir= photosSet.url(hash_openid) + '/' + fn

python代码

@app.route('/api/v/upload/',methods=['POST','GET'])
def mp_img(openid):
    fn = time.strftime('%Y%m%d%H%M%S') + '_%d' % random.randint(0, 100) + '.png'
    avata = request.files.get('test')
    hash_openid = md5(openid)
    new = compression_img(avata)
    creat_folder(os.path.join(app.config['UPLOADS_FOLDER'], hash_openid))
    pic_dir = os.path.join(app.config['UPLOADS_FOLDER'], hash_openid, fn)
    new.save(pic_dir)
    folder = photosSet.url(hash_openid)
	img_dir= folder + '/' + fn
    return img_dir
@app.route('/api/v/userinfo',methods=['POST'])
def userinfo():
    info = request.values.get('info')
    appid = 'wx000000000032332'  //这里填你的appid
    secret = 'jd82hhewh808b3sddada915e0b3' //你的secret_key
    user_info = json.loads(info)
    code = user_info['code']
    url = 'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code' % (
    appid, secret, code)
    data = requests.get(url).text
    session_ = json.loads(data)
    session_key = session_['session_key']
    encryptedData = user_info['encryptedData']
    iv = user_info['iv']
    pc = WXBizDataCrypt(appid, session_key)
    return pc.decrypt(encryptedData, iv)

你可能感兴趣的:(微信小程序)