阿里云对象存储 OSS(Object Storage Service)是一款海量、平安、低成本、高牢靠的云存储服务。本实例微信小程序直传文件参考官网文档:https://help.aliyun.com/zh/oss/use-cases/use-wechat-mini-prog...,应用STS长期拜访凭证拜访OSS官网文档:https://www.alibabacloud.com/help/zh/oss/developer-reference/...,另外应用STS进行长期受权之PHP受权拜访参考官网文档:https://help.aliyun.com/zh/oss/developer-reference/authorize-...。应用STS受权用户间接拜访OSS的流程如下:
开明阿里云OSS开明阿里云oss试用版:https://free.aliyun.com/?pipCode=oss&spm=5176.7933691.J_52537...
创立存储空间Bucket存储空间(Bucket)是用于存储对象(Object)的容器
创立Bucket存储目录文件列表新建test目录作为图片寄存地位
获取Bucket名称和Bucket域名点击浏览进入Bucket根本信息,保留存储空间名称、Endpoint地区节点、Bucket域名
创立RAM用户与角色云账号 AccessKey 是您拜访阿里云 API 的密钥,具备账户的齐全权限,应用 RAM 用户(而不是云账号)的 AccessKey 进行 API 调用
获取AccessKey ID和AccessKey Secret
为RAM用户增加权限:AliyunOSSFullAccess、AliyunSTSAssumeRoleAccess,在左侧搜寻框输出AliyunOSSFullAccess与AliyunSTSAssumeRoleAccess进行增加,而后点确定进行保留。
创立角色:第一步抉择阿里云账号
第二步配置角色
创立实现之后点击“为角色受权”
还是增加AliyunOSSFullAccess、AliyunSTSAssumeRoleAccess权限,在左侧搜寻框输出AliyunOSSFullAccess与AliyunSTSAssumeRoleAccess进行增加,而后点确定进行保留。
获取角色ARN
为角色授予上传文件的权限在创立权限策略页面,单击脚本编辑,而后在策略文档输入框中赋予角色向指标存储空间examplebucket下的目录上传文件的权限。具体配置示例如下。
创立Bucket受权策略
配置Bucket跨域拜访客户端进行表单直传到OSS时,会从浏览器向OSS发送带有Origin头的申请音讯。OSS对带有Origin头的申请音讯会进行跨域规定(CORS)的验证。因而须要为Bucket设置跨域规定以反对Post办法。
微信小程序配置域名白名单为微信小程序配置域名白名单,以实现微信小程序和OSS Bucket之间的失常通信。登录微信小程序平台,将上传和下载的非法域名填写为Bucket的外网拜访域名。
服务端生成签名应用服务端签名时,须要先搭建一个签名服务,而后由客户端调用签名服务生成签名。本例应用Thinkphp6生成签名。首先装置thinkphp6:
C:\phpstudy_pro\WWW> composer create-project topthink/think tp
应用composer require alibabacloud/sts-20150401命令装置STS依赖,应用composer require alibabacloud/sdk命令装置PHP SDK依赖。
C:\phpstudy_pro\WWW>tp> composer require alibabacloud/sts-20150401C:\phpstudy_pro\WWW>tp> composer require alibabacloud/sdk
创立生成签名控制器api.php、配置文件upload.php
upload.php文件配置阿里云oss参数
<?phpreturn ['storage' => '0','oss_ak' => '',//阿里云AccessKeyId 'oss_sk' => '',//阿里云AccessKeySecret''oss_host' => '',//阿里云Bucket 域名'oss_endpoint' => 'oss-cn-hangzhou.aliyuncs.com',//阿里云 Endpoint(地区节点)'oss_bucket' => '',//bucket名称'oss_role_arn' => '', // 角色访问控制RoleArn'oss_role_session_name' => 'stahangdeng', // 长期凭证名称,随便];
后端代码实现
<?phpnamespace app\controller;use think\Request;use think\facade\Config;use AlibabaCloud\Client\AlibabaCloud;use AlibabaCloud\Client\Exception\ClientException;use AlibabaCloud\Client\Exception\ServerException;use app\BaseController;class Api extends BaseController{ private $ak=''; private $sk=''; private $host=''; private $bucket=''; private $endpoint=''; private $roleArn=''; private $roleSessionName=''; public function __construct(Request $request){ //配置阿里云参数 empty($this->ak) && $this->ak = Config::get('upload.oss_ak'); empty($this->sk) && $this->sk = Config::get('upload.oss_sk'); empty($this->host) && $this->host = Config::get('upload.oss_host'); empty($this->bucket) && $this->bucket = Config::get('upload.oss_bucket'); empty($this->endpoint) && $this->endpoint = Config::get('upload.oss_endpoint'); empty($this->roleArn) && $this->roleArn = Config::get('upload.oss_role_arn'); empty($this->roleSessionName) && $this->roleSessionName = Config::get('upload.oss_role_session_name'); } /** * 阿里云Sts凭证 */ public function getStsToken(){ AlibabaCloud::accessKeyClient($this->ak, $this->sk) ->regionId('cn-hangzhou') ->asDefaultClient(); try { $result = AlibabaCloud::rpc() ->product('Sts') ->scheme('https') // https | http ->version('2015-04-01') ->action('AssumeRole') ->method('POST') ->host('sts.aliyuncs.com') ->options([ 'query' => [ 'RegionId' => "cn-hangzhou", 'RoleArn' => $this->roleArn, 'RoleSessionName' => $this->roleSessionName, ], ]) ->request(); $resultObj = $result->toArray(); $credentials = $resultObj['Credentials']; $credentials['host'] = $this->host; return json($credentials); } catch (ClientException $e) { return error($e->getErrorMessage()); } catch (ServerException $e) { return error($e->getErrorMessage()); } }
uniapp搭建小程序创立我的项目
把我的项目运行到微信开发者工具
运行到小程序模拟器
装置crypto-js和base64-js执行以下命令装置js
C:\phpstudy_pro\WWW\wx-uniapp> npm install crypto-jsC:\phpstudy_pro\WWW\wx-uniapp> npm install js-base64
引入js
import crypto from 'crypto-js';import { Base64 } from 'js-base64';
前端代码实现
在wx-uniapp\pages\index\index.vue文件增加以下代码
<template><view class="content"><view class="cell-left"><view class="cell-text">照片上传:</view><view class="cell-text" style="color: #8C8C8C;width: 180px;">(最多上传3张图片)</view></view><view class="cell-left"><view class="qtpicker"><!-- 选中待上传的图片 --><view class="preImgs" v-for="(val,index) in preImgUrl" :key='index'><image style="border-radius: 6px;" mode="" :src="val" @click="showImg(val,index)"></image><!-- 删除某张图片 --><view v-show="isShowDelImgBtn"><image class="cuo" mode="" src="/static/delete-icon.png" @click="delImg(index)"></image></view></view><view v-show="isShowAddImgBtn"><view class="img-item upload-icon" @click="chooseImg"></view></view></view></view></view></template><script>import crypto from 'crypto-js';import { Base64 } from 'js-base64';export default {data() {return {//title: 'Hello',preImgUrl: [], //本地预览的图片数据ossAccessKeyId:'',ossAccessKeySecret:'',host:'',securityToken:'',policy:'',isShowDelImgBtn:true,isShowAddImgBtn: true,}},onLoad() {},created() {this.getStsToken();},methods: {// 将办法标记为异步async getStsToken() {let that = this// 调用后端接口const result = uni.request({url: 'http://localhost/api/getStsToken',method: 'POST',}).then(response => {// response 就是 Promise 的 [[PromiseResult]] 属性对应的值const { data } = response;console.log(data);// 当初你能够间接拜访和过滤data中的内容this.host = data.host;that.ossAccessKeyId = data.AccessKeyId;that.ossAccessKeySecret = data.AccessKeySecret;that.securityToken = data.SecurityToken;const policyText = {expiration: data.Expiration, // policy过期工夫。依据本人接口返回的格局进行获取数据conditions: [// 限度上传大小。["content-length-range", 0, 1024 * 1024 * 1024],],};this.policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。}).catch(error => {console.error('获取STS Token时出错:', error);});},computeSignature(accessKeySecret, canonicalString) {return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));},// 抉择图片chooseImg() {let that = thisuni.chooseImage({// count: 容许上传的照片数量count: 3, //h5无奈限度// sizeType: original 原图,compressed 压缩图,默认二者都有sizeType: "original,compressed",success: function(res) { //抉择胜利,将图片存入本地长期门路,可删除,可查看,期待上传console.log(res, '抉择胜利')// 如果限度图片大小,则增加判断res.tempFiles.map(val => {// 判断本次上传限度的图片大小if (val.size > 10485760) {uni.showToast({icon: 'none',title: '上传的图片大小不超过10M'})return}// 判断本次最多上传多少照片that.imgNum++if(that.imgNum==3){that.isShowAddImgBtn=falseuni.showToast({icon: 'none',title: '最多上传3张图片'})}if (that.imgNum > 3) {that.imgNum = 3uni.showToast({icon: 'none',title: '上传的图片最多不能超过3张'})return}const filePath = val.path; // 待上传文件的文件门路。//把长期门路增加进数组,渲染到页面that.preImgUrl.push(filePath) // 退出工夫戳-免得文件名反复let unixTime = String(Date.parse(new Date()) / 1000)//获取最初一个.的地位let fileIndex = filePath.lastIndexOf(".");//获取文件后缀let fileExt = filePath.substring(fileIndex + 1);//文件名 let key = 'test/'+unixTime+'.'+fileExt;const signature = that.computeSignature(that.ossAccessKeySecret, that.policy);console.log(signature);//上传图片到阿里云ossconst host = that.host;const policy = that.policy;const ossAccessKeyId = that.ossAccessKeyId;const securityToken = that.securityToken; uni.uploadFile({url: host,filePath: filePath,name: 'file', // 必须填file。formData: {key,policy,OSSAccessKeyId: ossAccessKeyId,signature,'x-oss-security-token': securityToken,//success_action_status: 200, // 自定义胜利返回的http状态码,默认为204},success: (res) => {console.log(res);if (res.statusCode === 204) {//console.log('上传胜利');}},fail: err => {console.log(err);}});})}})},//点击小图查看大图片showImg(val, index) {console.log(val, '点击了')let that = thisuni.previewImage({// 对选中的图片进行预览urls: that.preImgUrl, //图片数组 // urls:['',''] 图片的地址 是数组模式current: index, //以后图片的下标})},//删除某张图片,从本地的长期门路图片中, 删除门路即可delImg(index) {this.imgNum--;this.preImgUrl.splice(index, 1)if(this.imgNum<3){this.isShowAddImgBtn=true;}},}}</script><style lang="scss" scoped>.content {display: flex;flex-direction: column;align-items: center;justify-content: center;}.logo {height: 200rpx;width: 200rpx;margin-top: 200rpx;margin-left: auto;margin-right: auto;margin-bottom: 50rpx;}.text-area {display: flex;justify-content: center;}.title {font-size: 36rpx;color: #8f8f94;}.upload-icon {box-sizing: border-box;border: 2rpx solid #bfbfbf;}.upload-icon:before {content: '';position: absolute;top: 50%;left: 50%;width: 60rpx;height: 6rpx;background-color: #bfbfbf;margin: -3rpx 0 0 -30rpx;border-radius: 5rpx;}.upload-icon::after {content: '';position: absolute;top: 50%;left: 50%;width: 6rpx;height: 60rpx;background-color: #bfbfbf;margin: -30rpx 0 0 -3rpx;border-radius: 5rpx;}.cell-left {display: flex;align-items: center;padding: 8px;.cell-icon {width: 50rpx;height: 50rpx;}.cell-text {color: #595959 ;font-size: 15px;margin-left: 20rpx;//width: 180rpx;}}.img-item {width: 150rpx;height: 150rpx;position: relative;box-sizing: border-box;margin: 15rpx;.img {width: 100%;height: 100%;}.img-delete-box {width: 40rpx;height: 40rpx;position: absolute;right: 0;top: 0;.img-delete-icon {width: 100%;height: 100%;}}}.qtpicker {width: 100%;display: flex;flex-direction: row;flex-wrap: wrap;margin: 0 auto;padding: 10rpx 0;.preImgs {margin: 13rpx;position: relative;image {width: 200rpx;height: 200rpx;}.cuo {width: 17pt;height: 17pt;//line-height: 12px;//text-align: center;///* font-size: 16px; *///border-radius: 50%;//background-color: #223E4B;//color: #FFFFFF;position: absolute;right: 0px;top: 0px;}}}</style>
上传图片前端微信小程序开发工具点击图片上传,图片上传胜利返回code204
Bucket文件列表显示上传图片胜利
点击图片详情,图片失常显示
到此微信小程序上传图片到阿里云oss胜利