小程序(uniapp)上传头像至OSS(阿里云)--保姆级

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: 前言自微信小程序改版以来,现在获取用户的头像和昵称就不能直接通过wx.getUserInfo获取了。而是需要用户主动在登录后填写自己的昵称和头像,微信只是提供一个一键填写的快捷操作让用户直接使用自己已有的微信昵称或头像。

小程序(uniapp)上传头像至OSS(阿里云)--保姆级

前言


微信小程序改版以来,现在获取用户的头像和昵称就不能直接通过wx.getUserInfo获取了。而是需要用户主动在登录后填写自己的昵称和头像,微信只是提供一个一键填写的快捷操作让用户直接使用自己已有的微信昵称或头像。

如果是想做一个比较完善的小程序系统,那么头像昵称的修改可谓是每个带用户的小程序开发都需要经历的。

昵称还好,就是一个文本字符串,但是头像的话我们就需要上传至自己的服务器或者是一些云对象存储服务,这里我选择的是阿里云OSS服务,下面开始我的保姆级教程

流程概览


如上是整个上传头像的一个时序图,总的来说有这五步:

  1. 通过微信自带组件获取用户选择头像的临时文件路径
  2. 获取对OSS的操作授权
  3. 配置后端服务生成临时授权的服务
  4. 获取授权并上传文件至OSS
  5. 将新的头像路径保存到数据库用户表中

好,接下来我们就以上述五步慢慢道来:

1. 获取头像临时路径



据描述:是要将 button 组件 open-type 的值设置为 chooseAvatar,当用户选择需要使用的头像之后,可以通过 bindchooseavatar 事件回调获取到头像信息的临时路径。

所以笔者编写了如下代码:

// template
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
  <uni-icons type="forward" size="30" color="#D3D3D3"></uni-icons>
</button>


// script
function onChooseAvatar(e: any) {
  console.log("choose avatar: ", e.detail);
  user.avatarUrl = e.detail.avatarUrl;
}


为了让button样式透明,所以style代码如下

.avatar-wrapper {
  padding-left: 0;
  padding-right: 0;
  height: 50px;
  line-height: 50px;
  background-color: transparent;
  border-color: transparent;
}
.avatar-wrapper::after {
  border: none;
}


这里笔者在button里面包裹了一个icon,因为我不想要button的样式,而仅仅用户点击icon就可以修改头像。

此时我们点击就可以获取头像的临时路径了:

然后我们选择微信头像或者本地上传的图片后就可以出现如下的日志信息:

到这里,我们这一步就已经完成了,已经获取到如上的头像临时路径了...

2. 获取OSS操作授权


这里假设你已经开通了OSS服务 ,开通过程非常简单,毕竟花钱的过程一般来说都是非常简单的,一步到位🤬。这里就不过多赘述了。

如果你想要你的OSS服务拥有自己的专属域名以及CDN加速的话,可以查看我之间写的这篇文章--CDN实践配置+原理篇

首先我们创建一个我们阿里云账号的子用户,这个子用户我们后续会将它授权给我们的服务器,让我们的服务器操作该子用户,拥有其拥有的权限。你的就是我的🤭

1)配置阿里云-访问控制

按照上述的流程点击创建后,就会出现如下页面,这里值得注意的是我们需要保存好其中的accessKeyId以及accessKeySecret

拥有这个Id+Secret相当于我们就拥有了这个用户的身份,就可以操作该身份具有的资源了,但是此时我们还没有赋予其任何权限,所以这里我们赋予其操作OSS的权限,尽量不要赋予过多的权限,做好权限收敛:

当然,如果你有多个用户有同样的权限操作,也可以使用用户组进行管理,这里不展开了。

点击添加权限,选择AliyunOSSFullAccess

2)配置阿里云-OSS-细化授权

然后我们继续对OSS进行细化配置:

3)配置阿里云-OSS-跨域访问

如果你的OSS之前已经可以访问了,这里就不需要配置了,如果是第一次配置,那么记得还要对OSS进行跨域访问的配置,这也是很多网友出现403的主要原因。

好,此时我们就拥有了一个有效的AccesssKeyIdAccessKeySecretl了

3. 配置服务器


这里我使用的是服务端签名,你也可以使用客户端签名临时凭证。并且我这里使用的后端技术栈是NestJS + GraphQl,如果你是其他技术栈,可以参考原官方文档进行自定义

0)安装

npm i crypto-js @types/crypto-js


/src/utils/oss.interface.ts

export interface MpUploadOssHelperOptions {
  // 阿里云账号AccessKey
  accessKeyId: string;
  // 阿里云账号AccessId
  accessKeySecret: string;
  // 限制参数的生效实践,单位为小时,默认值为1
  timeout?: number;
  // 限制上传文件大小,单位为MB,默认值为10
  maxSize?: number;
}


2)/src/utils/oss.ts

import * as crypto from 'crypto-js';
import { MpUploadOssHelperOptions } from './oss.interface';
// 详见:https://help.aliyun.com/document_detail/92883.html
export class MpUploadOssHelper {
  private accessKeyId: string;
  private accessKeySecret: string;
  private timeout: number;
  private maxSize: number;
  constructor(options: MpUploadOssHelperOptions) {
    this.accessKeyId = options.accessKeyId;
    this.accessKeySecret = options.accessKeySecret;
    // 限制参数的生效时间,单位为小时,默认值为1。
    this.timeout = options.timeout || 1;
    // 限制上传文件的大小,单位为MB,默认值为10。
    this.maxSize = options.maxSize || 10;
  }
  createUploadParams() {
    const policy = this.getPolicyBase64();
    const signature = this.signature(policy);
    return {
      OSSAccessKeyId: this.accessKeyId,
      policy: policy,
      signature: signature,
    };
  }
  getPolicyBase64() {
    const date = new Date();
    // 设置policy过期时间。
    date.setHours(date.getHours() + this.timeout);
    const srcT = date.toISOString();
    const policyText = {
      expiration: srcT,
      conditions: [
        // 限制上传文件大小。
        ['content-length-range', 0, this.maxSize * 1024 * 1024],
      ],
    };
    const buffer = Buffer.from(JSON.stringify(policyText));
    return buffer.toString('base64');
  }
  signature(policy) {
    return crypto.enc.Base64.stringify(
      crypto.HmacSHA1(policy, this.accessKeySecret)
    );
  }
}


3)src/oss/models/oss.model.ts

import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class Oss {
  @Field()
  OSSAccessKeyId: string;
  @Field()
  policy: string;
  @Field()
  signature: string;
}


4)src/oss/oss.module.ts

import { Module } from '@nestjs/common';
import { OssService } from './oss.service';
import { OssResolver } from './oss.resolver';
@Module({
  providers: [OssService, OssResolver],
})
export class OssModule {}


5)src/oss/oss.service.ts

import { Injectable } from '@nestjs/common';
import { MpUploadOssHelper } from 'src/utils/oss';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class OssService {
  constructor(private readonly configService: ConfigService) {}
  getPostObjectParams() {
    const mpHelper = new MpUploadOssHelper({
      accessKeyId: this.configService.get<string>('ACCESS_KEY_ID'),
      accessKeySecret: this.configService.get<string>('ACCESS_KEY_SECRET'),
      timeout: 1,
      maxSize: 1,
    });
    // 生成参数
    const params = mpHelper.createUploadParams();
    return params;
  }
}


注意:这里我是通过环境变量获取的IDKEY,环境变量的使用可参考这篇文章

6)src/oss/oss.resolve.ts或者src/oss/oss.controller.ts

这里就体现了service作为业务层的作用了,无论我们是想使用GraphQL,还是使用REST API暴露接口,都可以非常灵活的替换,如下是GraphQL的代码:


import { UseGuards } from '@nestjs/common';
import { Resolver, Query } from '@nestjs/graphql';
import { GqlAuthGuard } from 'src/auth/gql-auth.guard';
import { Oss } from './models/oss.model';
import { OssService } from './oss.service';
@Resolver()
export class OssResolver {
  constructor(private readonly ossService: OssService) {}
  @UseGuards(GqlAuthGuard)
  @Query(() => Oss)
  getPostObjectParams() {
    return this.ossService.getPostObjectParams();
  }
}


演示:

4. 上传文件至OSS


如下代码,这里使用的是GraphQL请求的接口,如果你是使用的REST API,基本流程也是一样的:

async function uploadAvatar(filePath: string) {
  // 1. 请求服务端签名凭证
  const { execute } = useQuery({ query: getPostObjectParamsGQL });
  uni.showLoading({ title: "正在请求上传凭证中..." });
  const { error, data } = await execute();
  if (error) {
    uni.showToast({
      title: `上传头像失败: ${error}`,
      icon: "error",
      duration: 2000,
    });
    throw new Error(`上传头像失败: ${error}`);
  }
  // 2. 上传图片至oss
  const { OSSAccessKeyId, policy, signature } = data?.getPostObjectParams || {};
  const imgType = filePath.split(".").pop();
  const key = `wxmp/${userData?.id}.${imgType}`;
  uni.showLoading({ title: "正在上传图片中..." });
  const ossRes = await uniUploadFile({
    url: ossHost, // 开发者服务器的URL。
    filePath,
    name: "file", // 必须填file。
    formData: {
      key,
      policy,
      OSSAccessKeyId,
      signature,
    },
  });
  uni.hideLoading();
  return ossHost + "/" + key;
}


上述代码我是以用户的uid重命名图片文件的,就是key这个属性值,你也可以自定义你自己的文件命名方式。

演示:

然后OSS中就可以查看到这张图片了:

5. 保存数据库用户表


这一步其实就很简单了,也没什么参考价值,就是请求API,然后保存到数据库就可以了,具体代码就不贴了,如下是效果:

最后


小程序的开发几乎是程序员的必备操作,自带流量,前期非常好用,不过就是开发文档确实看着不舒服,平台改版我们也需要跟着改版...

然后用户登录以及自定义头像都是小程序们非常常见的操作,这里演示一下过程希望对你有所帮助,如果有操作不当,欢迎在评论区中友善指出..


相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
目录
相关文章
|
27天前
|
小程序 前端开发 关系型数据库
基于Uniapp+php校园小程序,校园圈子论坛系统功能,校园跑腿二手交流功能设计
校园圈子论坛及综合服务平台集成了校园跑腿、兼职信息、外卖团购、闲置交换、租赁服务、表白墙等多功能模块,提供一站式校园生活解决方案。系统采用uniapp前端和PHP后端开发,支持多城市、多学校切换,配备分站式后台管理,确保稳定性和安全性。通过融云IM SDK实现即时通讯功能,增强用户互动与粘性。适用于大学校园、城市及社区圈子,满足多样化需求,提升便捷体验。
|
26天前
|
小程序 前端开发 关系型数据库
uniapp跨平台框架,陪玩系统并发性能测试,小程序源码搭建开发解析
多功能一体游戏陪练、语音陪玩系统的开发涉及前期准备、技术选型、系统设计与开发及测试优化。首先,通过目标用户分析和竞品分析明确功能需求,如注册登录、预约匹配、实时语音等。技术选型上,前端采用Uni-app支持多端开发,后端选用PHP框架确保稳定性能,数据库使用MySQL保证数据一致性。系统设计阶段注重UI/UX设计和前后端开发,集成WebSocket实现语音聊天。最后,通过功能、性能和用户体验测试,确保系统的稳定性和用户满意度。
|
2月前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
|
1月前
|
移动开发 小程序 前端开发
超详细攻略!uniapp陪玩系统,打包陪玩小程序、H5需要注意什么?
陪玩系统的打包过程涵盖APP、小程序和H5平台。APP打包需使用uni-app开发工具,配置项目信息并选择云打包;小程序打包需在微信公众平台注册账号并提交审核;H5打包则直接通过uni-app生成文件并上传至服务器。各平台需注意权限配置、代码规范及充分测试,确保应用稳定性和兼容性。
|
30天前
|
移动开发 小程序
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
27 0
|
3月前
|
人工智能 小程序 搜索推荐
uni app下开发AI运动小程序解决方案
本文介绍了在小程序中实现AI运动识别的解决方案。该方案依托于UNI平台,通过高效便捷的插件形式,实现包括相机抽帧控制、人体识别、姿态识别等在内的多项功能,无需依赖后台服务器,大幅提高识别效率和用户体验。方案内置多种运动模式,支持自定义扩展,适用于AI健身、云上赛事、AI体测等多场景,适合新开发和存量改造项目。
|
3月前
|
小程序 前端开发 JavaScript
在线课堂+工具组件小程序uniapp移动端源码
在线课堂+工具组件小程序uniapp移动端源码
82 0
在线课堂+工具组件小程序uniapp移动端源码
|
4月前
|
移动开发 小程序 数据可视化
基于npm CLI脚手架的uniapp项目创建、运行与打包全攻略(微信小程序、H5、APP全覆盖)
基于npm CLI脚手架的uniapp项目创建、运行与打包全攻略(微信小程序、H5、APP全覆盖)
567 3
|
4月前
|
小程序 API
微信小程序更新提醒uniapp
在小程序开发中,版本更新至关重要。本方案利用 `uni-app` 的 `uni.getUpdateManager()` API 在启动时检测版本更新,提示用户并提供立即更新选项,自动下载更新内容,并在更新完成后重启小程序以应用新版本。适用于微信小程序,确保用户始终使用最新版本。以下是实现步骤: ### 实现步骤 1. **创建更新方法**:在 `App.vue` 中创建 `updateApp` 方法用于检查小程序是否有新版本。 2. **测试**:添加编译模式并选择成功状态进行模拟测试。
96 0
微信小程序更新提醒uniapp
|
4月前
|
移动开发 小程序 数据可视化
一招学会DIY官网可视化设计支持导出微擎、UNIAPP、H5、微信小程序源码
一招学会DIY官网可视化设计支持导出微擎、UNIAPP、H5、微信小程序源码
79 2

热门文章

最新文章