官方文档
开发思路
按照上面得文档依次设置好权限和参数,最重要的是设置sts服务得时候需要把相关AccessKeyId、AccessKeySecret、RoleArn记好保存下来,搭建sts服务器得时候需要用到。震哥哥过程最主要得就是研究好上面俩个文档就行了。
小程序端核心代码示例
小程序端需要用到俩个依赖库 crypto Base64
第一步 搭建小程序sts鉴权生成函数
import crypto from './crypto.js';
import { Base64 } from './js-base64';
import apiService from '../apiservices/api';
// 保存计算好得 sts 密钥 (因为这个密钥可以用一段时间,所以需要协议一个过期自动获取的机制)
let formDataParams = null;
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
// 生成的签名能力 读、写
const policyText = (expiration) => ({
expiration: expiration, // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
})
async function getFormDataParams() {
// 提前5s 获取最新的密钥
if (!formDataParams || (formDataParams.expiration - 5) < (Date.now() / 1000)) {
// sts鉴权所需的重要参数 需要从搭建好的sts后端服务获取 包含以下参数 AccessKeyId AccessKeySecret SecurityToken Expiration
const credentials = await apiService.GetStsAccessKey();
// policy必须为base64的string。
const policy = Base64.encode(JSON.stringify(policyText(credentials.Expiration)))
const signature = computeSignature(credentials.AccessKeySecret, policy)
formDataParams = {
OSSAccessKeyId: credentials.AccessKeyId,
signature,
policy,
'x-oss-security-token': credentials.SecurityToken,
expiration: credentials.Expiration
}
return formDataParams
}
return formDataParams
}
module.exports = {
getFormDataParams: getFormDataParams
}
第二步 书写 oss 上传函数
const app = getApp();
import { getFormDataParams } from '../utils/sts';
const ossUploadService = {
// 这个通用函数 只需要传 上传路径(桶名+文件名) 文件的本地路径就可以了
async upload(key, filePath) {
return new Promise(async (resolve, reject) => {
const stsInfo = await getFormDataParams()
// 需要上传到阿里云oss的地方
const host = app.globalData.ossUrl;
const signature = stsInfo.signature;
const ossAccessKeyId = stsInfo.OSSAccessKeyId;
const policy = stsInfo.policy;
const securityToken = stsInfo['x-oss-security-token'];
wx.uploadFile({
url: host, // 阿里 oss URL。
filePath: filePath, // 上传文件的本地路径
name: 'file', // 必须填file。
formData: {
key, // 文件名
policy,
OSSAccessKeyId: ossAccessKeyId,
signature,
'x-oss-security-token': securityToken // 使用STS签名时必传。
},
success: (res) => {
if (res.statusCode === 204) {
// 返回oss文件的路径
resolve(`${app.globalData.ossUrl}/${key}`);
}
},
fail: err => {
reject(err)
},
complete: res => {
console.log('UPLOAD', key, filePath, res.statusCode, res.data);
}
})
})
}
}
module.exports = ossUploadService
第三步 在具体业务中使用
async upload() {
const guid = util.getGuid();
// file 包含 大小 路径 封面路径 时长等
const file = await wx.chooseMedia({
sourceType: ['album'],
count: 1,
mediaType: ['video']
})
// 上传视频
const videoKey = `video/${guid}`;
const videoFilePath = file.tempFiles[0].tempFilePath;
const ossVideoUrl = await ossUploadService.upload(videoKey, videoFilePath);
// 上传封面
const imageKey = `image/${guid}`;
const imageFilePath = file.tempFiles[0].thumbTempFilePath;
const ossImageUrl = await ossUploadService.upload(imageKey, imageFilePath);
console.log(ossVideoUrl, ossImageUrl);
},
})
完整的小程序代码片段(内部包含上面提到的工具)
node 服务端 核心代码
const express = require('express');
const { STS } = require('ali-oss');
const fs = require('fs');
const app = express();
const path = require('path');
const conf = require('./config');
app.get('/sts', (req, res) => {
console.log(conf);
let policy;
if (conf.PolicyFile) {
policy = fs.readFileSync(path.resolve(__dirname, conf.PolicyFile)).toString('utf-8');
}
const client = new STS({
accessKeyId: conf.AccessKeyId,
accessKeySecret: conf.AccessKeySecret
});
client.assumeRole(conf.RoleArn, policy, conf.TokenExpireTime).then((result) => {
console.log(result);
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-METHOD', 'GET');
res.json({
AccessKeyId: result.credentials.AccessKeyId,
AccessKeySecret: result.credentials.AccessKeySecret,
SecurityToken: result.credentials.SecurityToken,
Expiration: result.credentials.Expiration
});
}).catch((err) => {
console.log(err);
res.status(400).json(err.message);
});
});
app.use('/static', express.static('public'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '../index.html'));
});
app.listen(8000, () => {
console.log('App started.');
});