阿里云OSS 小程序直传实践

官方文档

开发思路

按照上面得文档依次设置好权限和参数,最重要的是设置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);
  },

})

完整的小程序代码片段(内部包含上面提到的工具)

github地址

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.');
});

完整的node代码

github地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值