阿里云对象存储 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-20150401
C:\phpstudy_pro\WWW>tp> composer require alibabacloud/sdk
创立生成签名控制器api.php、配置文件upload.php
upload.php文件配置阿里云oss参数
<?php
return [
'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', // 长期凭证名称,随便
];
后端代码实现
<?php
namespace 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-js
C:\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 = this
uni.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=false
uni.showToast({
icon: 'none',
title: '最多上传3张图片'
})
}
if (that.imgNum > 3) {
that.imgNum = 3
uni.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);
//上传图片到阿里云oss
const 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 = this
uni.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胜利
发表回复