微信小程序直传阿里云OSS

需求描述

在使用uni-app开发社区模块时,发布帖子拥有上传图片的功能,uni-app提供上传文件的API——uni.uploadFile。
uploadFile的功能是将本地url图片以post请求的方式上传到资源服务器中,思来想去决定使用阿里云OSS作为资源服务器。

参考:
微信小程序直传实践

该文档罗列了3个步骤:

  1. 配置白名单
  2. 提供签名服务
  3. 使用uni.uploadFile上传资源文件

第一步太基础了就不再介绍。
直接介绍第二步:

1 提供签名服务

在阿里云 OSS 中,资源的访问和操作(上传、下载、删除等)都受到严格的权限控制,默认情况下,只有拥有权限的用户或客户端才能执行这些操作。为了确保安全,OSS 使用签名机制来验证每个请求的合法性。
权限控制:OSS 中的每个存储空间(Bucket)和对象(文件)都可以设置访问权限,例如:

  • 私有(Private):默认状态,只有拥有正确权限或签名的人可以访问或修改。
  • 公共读私有写(Public Read, Private Write):所有人可以读取资源,但只有有权限的人可以上传或修改。
  • 公共读写(Public Read Write):所有人都可以读写资源(不推荐)。

签名机制: 为了确保访问和操作 OSS 资源的安全性,阿里云要求每个访问请求都要有合法的签名,尤其是私有资源。这些签名可以通过两种方式获取:

  • 静态凭证:通过 AccessKeyId 和 AccessKeySecret
    为每个请求生成签名。这个方式适用于有固定后端应用的场景,但不建议直接在客户端暴露这些凭证。
  • 临时授权(STS):为了更加灵活且安全地处理 OSS 的访问和操作,阿里云提供了 STS(安全令牌服务)。通过
    STS,你可以生成一个短时间有效的临时签名,客户端使用该签名进行上传或下载操作,而不会暴露敏感的凭证(AccessKeySecret)。

签名的作用: 签名本质上是对请求的加密验证,用来确保:

  • 请求的合法性:只有具有正确签名的人才能进行访问和操作。
  • 请求的时效性:签名通常会设置一个有效期,超出有效期的请求将被拒绝,确保安全性。
  • 最小化权限泄露:通过临时签名,你可以确保客户端只能在有限的时间内对指定的资源进行操作,避免长时间暴露权限。
1.1 签名服务在ECS服务器上的部署

Step1 安装Node.js

本节参考:下载Node.js

# 安装 nvm (Node 版本管理器)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash

# 下载并安装 Node.js(可能需要重启终端)
nvm install 20

# 验证环境中是否存在正确的 Node.js 版本
node -v # 应该打印 `v20.18.0`

# 验证环境中是否存在正确的 npm 版本
npm -v # 应该打印 `10.8.2`

在这里插入图片描述
在这里插入图片描述

如果在执行node -v时报如下错误,通常是因为新版的node v18开始,都需要GLIBC_2.27支持。

node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by node)
node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by node)
node: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by node)
node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by node)
node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node)
node: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by node)

查看一下系统目前的GLIBC版本:

strings /lib64/libc.so.6 | grep GLIBC_
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17

那就使用17版本的NodeJS就好了。

# 卸载node20
nvm uninstall 20
# 安装node17
nvm install 17

# 验证环境中是否存在正确的 Node.js 版本
node -v # 应该打印 `v17.9.1`

# 验证环境中是否存在正确的 npm 版本
npm -v # 应该打印 `8.11.0`

将node添加到环境变量中:

# 查看node的路径
which node
/root/.nvm/versions/node/v17.9.1/bin/node
# 修改环境变量配置文件
vim ~/.bash_profile
# 添加node路径
PATH=$PATH:$HOME/bin:/root/.nvm/versions/node/v17.9.1/bin
export PATH

Step2 安装OSS SDK

npm install ali-oss --save

Step3 安装express和https

由于微信小程序上传文件的服务器白名单必须以https开头,所以,必须拥有SSL证书,如何获取SSL证书本文不进行探讨。

npm install https
npm install express
npm install fs

然后在/var/www/下创建一个node项目目录

mkdir node-project
cd node-project
node init -y
vim app.js
const express = require('express');
const https = require("https");
const app = express();
const fs = require('fs');

const httpsOption = {
        key:fs.readFileSync("/xxxxxxxxxxxxxxxxxxxxxx.key"),
        cert: fs.readFileSync("/xxxxxxxxxxxxxxxxxxxxxx.pem")
}

const server = https.createServer(httpsOption, app)

app.get('/', (req, res) => {
    res.send('Hello from Express!');
});

server.listen(3000, () => {
    console.log('Server running at http://127.0.0.1:3000/');
});

安装pm2模块自动启动nodejs:

npm insatll pm2 -g
cd /var/www/node-project
pm2 start app.js
pm2 startup systemd
pm2 ls

然后在浏览器中输入

https://your_domain:3000/

就可以看到:
在这里插入图片描述

Step4 编辑服务器端签名代码

先安装crypto模块:

npm install crypto-js

在/var/www/node-project下创建uploadOssHelper.js文件,代码如下:

const crypto = require("crypto-js");

class MpUploadOssHelper {
  constructor(options) {
    this.accessKeyId = options.accessKeyId;
    this.accessKeySecret = options.accessKeySecret;
    // 限制参数的生效时间,单位为小时,默认值为1。
    this.timeout = options.timeout || 1; 
    // 限制上传文件的大小,单位为MB,默认值为10。
    this.maxSize = options.maxSize || 10;
  }

  createUploadParams() {
    const policy = this.getPolicyBase64();
    const signature = this.signature(policy);
    return {
      OSSAccessKeyId: this.accessKeyId,
      policy: policy,
      signature: signature,
    };
  }

  getPolicyBase64() {
    let date = new Date();
    // 设置policy过期时间。
    date.setHours(date.getHours() + this.timeout);
    let srcT = date.toISOString();
    const policyText = {
      expiration: srcT,
      conditions: [
        // 限制上传文件大小。
        ["content-length-range", 0, this.maxSize * 1024 * 1024],
      ],
    };
    const buffer = Buffer.from(JSON.stringify(policyText));
    return buffer.toString("base64");
  }

  signature(policy) {
    return crypto.enc.Base64.stringify(
      crypto.HmacSHA1(policy, this.accessKeySecret)
    );
  }
}

module.exports = MpUploadOssHelper;

使用dotenv模块来加载环境变量到process.env

npm install dotenv

在项目的根目录下创建.env文件(/var/www/node-project/.env),并添加环境变量:

OSS_ACCESS_KEY_ID=your-access-key-id
OSS_ACCESS_KEY_SECRET=your-access-key-secret

关于如何获取AccessKey和AccessKeySecret,请参考:创建AccessKey

同时请确保Bucket的授权策略添加了授权的用户。
在这里插入图片描述

然后编辑app.js

require('dotenv').config();
const express = require('express');
const https = require("https");
const app = express();
const fs = require('fs');
const MpUploadOssHelper = require("./uploadOssHelper.js");//导入

const httpsOption = {
        key:fs.readFileSync("/xxxxxxxxxxxxxxxxxxx.key"),
        cert: fs.readFileSync("/xxxxxxxxxxxxxxx.pem")
}

const server = https.createServer(httpsOption, app)

app.get('/', (req, res) => {
    res.send('Hello from Express!');
});

app.get("/getPostObjectParams",(req, res) => {
        const mpHelper = new MpUploadOssHelper({
                accessKeyId: process.env.OSS_ACCESS_KEY_ID,
                accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
                // 限制参数的生效时间,单位为小时,默认值为1。
                timeout: 1,
                // 限制上传文件大小,单位为MB,默认值为10。
                maxSize: 10,
        });

        const params = mpHelper.createUploadParams();   // 生成参数

        res.json(params);
});

server.listen(3000, () => {
    console.log('Server running at http://127.0.0.1:3000/');
});

然后开启node.js

node app.js
Server running at http://127.0.0.1:3000/

2 使用uni.uploadFile上传资源文件

const host = '<host>';
const signature = '<signatureString>';
const ossAccessKeyId = '<accessKey>';
const policy = '<policyBase64Str>';
const key = '<object name>';
const securityToken = '<x-oss-security-token>'; 
const filePath = '<filePath>'; // 待上传文件的文件路径。
wx.uploadFile({
  url: host,
  filePath: filePath,
  name: 'file', // 必须填file。
  formData: {
    key,
    policy,
    OSSAccessKeyId: ossAccessKeyId,
    signature,
    // 'x-oss-security-token': securityToken // 使用STS签名时必传。
  },
  success: (res) => {
    if (res.statusCode === 204) {
      console.log('上传成功');
    }
  },
  fail: err => {
    console.log(err);
  }
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值