您现在的位置是:首页 >技术杂谈 >前端阿里云OSS直传,微信小程序版本网站首页技术杂谈

前端阿里云OSS直传,微信小程序版本

邱铁牛 2024-07-04 11:18:00
简介前端阿里云OSS直传,微信小程序版本

前言:

网络上许多的文章资料,全是使用阿里云官方的SDK,ali-oss插件去做直传。可是各位素未谋面的朋友要注意,这个SDK它支持web环境使用,也就是PC端浏览器

项目环境切换到微信小程序,是无法使用这种方式的,当然官方也有给出微信小程序直传的文档,继续往下看。

支持配置OSS直传的callback参数,这是其它文章中没用到的


官方:如何使用ali-oss进行直传icon-default.png?t=N4P3https://help.aliyun.com/document_detail/64041.html?spm=a2c4g.383954.0.0.43c25e89vo4jkS

官方:微信小程序OSS直传icon-default.png?t=N4P3https://help.aliyun.com/document_detail/92883.html?spm=a2c4g.31925.0.0.24de344egXVqTI

代码:

酒过三巡我还是少说话,多贴代码。并且把一些踩坑的地方告诉大家。继续往下看。

首先需要下载三个库。

注意:官方文档是让我们使用import { Base64 } from 'js-base64';   
可是它会它会报错!!!根本用不了。
所以需要换成import base64 from 'base-64';import utf8 from 'utf8'

npm install crypto-js --save

npm install base-64 --save

npm install utf8 --save


crypto-js:是阿里官方的签名库
base-64、utf8:是用来转码,配合crypto-js使用的


签名不都是后端的事情吗?没错大部分是后端。

但是我在官方文档看到客户端也可以签名,然后这么随口一说。

我亲爱的后端同事便说:客户端(前端)也可以签名,那就你自己签名吧。

配置callback(可选,根据后端要求来决定是否需要)

为什么需要使用callback,这就是后端的骚操作。
他要我们把文件顺利传到OSS后,再让OSS去请求他的接口。
他接口会去做一些业务逻辑,比如改文件的重命名。

而callback则是配置,后端处理业务逻辑的接口地址、接请求参数。


直传OSS配置callback是有格式要求的,并且微信小程序端、web端,callback的配置格式要求还不一样。
这里可能是因为用户们很少用到callback参数,官方文档写得也不准确。
大家按照我代码来,指定是没问题的,细节我不想说了,有问题评论区交流。

import crypto from 'crypto-js'
import base64 from 'base-64'
import utf8 from 'utf8'
<script>
methods: {

    chooseAvatarEvent(event) {
      const { avatarUrl } = event.detail

      this.getFormDataParams().then(() => {
        this.uploadFile(avatarUrl, 'tmp/', e => {})
      })
    },

    // 计算签名。
    computeSignature(accessKeySecret, canonicalString) {
      console.log(crypto.enc)
      return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret))
    },

    getPolicyBase64() {
      const date = new Date()
      date.setHours(date.getHours() + 1)
      const policyText = {
        expiration: date.toISOString(), // 设置policy过期时间。
        conditions: [
          // 限制上传大小。
          ['content-length-range', 0, 1024 * 1024 * 1024],
        ],
      }
      return policyText
    },

    async getFormDataParams() {
      // 获取STS临时token,这是后端接口做的,找亲爱的后端
      const credentials = await queryOssGetStsToken()
      const policyText = this.getPolicyBase64()
      const uft8Str = utf8.encode(JSON.stringify(policyText))
      const policy = base64.encode(uft8Str)
      const signature = this.computeSignature(credentials.AccessKeySecret, policy)

      const user_id = this.userInfo.user_id

      const callback = {
        // 设置回调请求的服务器地址,且要求必须为公网地址。
        // 后端的接口地址:https://www.baidu.com/api/xxxx
        callbackUrl: credentials.callbackUrl,
        // 设置回调请求消息头中Host的值,即您的服务器配置的Host值。
        // host: 'yourHost',
        // 设置发起回调时请求body的值。
        callbackBody: 'bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}&type=avatar&user_id=' +
						user_id,
        // 设置发起回调请求的Content-Type。
        callbackBodyType: 'application/x-www-form-urlencoded',
      }
      const uft8Str_callback = utf8.encode(JSON.stringify(callback))
      const base64_callback = base64.encode(uft8Str_callback)
      const formData = {
        OSSAccessKeyId: credentials.AccessKeyId,
        signature,
        policy,
        'success_action_status': '200',
        'x-oss-security-token': credentials.SecurityToken,
        callback: base64_callback,
      }
      this.formData = formData
      console.log('formData===', this.formData)
    },

    uploadFile(filePath, dir, successc, failc) {
      const _this = this
      // 获取上传的文件类型
      let fileTypeIndex = filePath.lastIndexOf('.')
      let fileType = filePath.substring(fileTypeIndex)

      //图片名字 可以自行定义,     这里是采用当前的时间戳 + 150内的随机数来给图片命名的
      // const aliyunFileKey = dir + new Date().getTime() + Math.floor(Math.random() * 150) + '.png';
      const aliyunFileKey = dir + new Date().getTime() + Math.floor(Math.random() * 150) + fileType

      uni.uploadFile({
        // 注意:阿里云OSS的访问地址,并不是接口请求域名
        url: 'http://pxxxxx-xxxx-xxx.oss-cn-shenzhen.aliyuncs.com', //阿里云OSS访问地址
        filePath: filePath, //要上传文件资源的路径
        name: 'file', //必须填file
        formData: {
          'key': aliyunFileKey,
          ...this.formData
        },
        callback: this.formData.callback,
        success: function(res) {
          const resObj = JSON.parse(res.data)
          _this.userInfo.avatar_id = resObj.data.id
          _this.userInfo.avatar = resObj.data.url
          console.log('上传成功===', resObj)
        },
        fail: function(err) {
         
          // err.wxaddinfo = aliyunServerURL
          // failc(err)
        },
      })
    }

  }
</script>
<template>
    <view class="item-panel flex-1">
	    <u-image :src="userInfo.avatar" width="80rpx" height="80rpx" shape="circle"></u-image>
	    <button class="upload-box" open-type="chooseAvatar" @chooseavatar="chooseAvatarEvent"></button>
        <view class="ml-20 flex ai-center">
	        <u-icon name="arrow-right"></u-icon>
	    </view>
    </view>
</template>

<style lang="scss" scoped>
    .item-panel {
		display: flex;
		position: relative;

		.upload-box {
			position: absolute;
			width: 100%;
			height: 100%;
			opacity: 0;
			right: 0;
			top: 0;
		}
	}
</style>

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。