阿里云OSS存储微信小程序图片数据

1.对象存储(Object Storage Service)介绍
OSS 指云存储服务‌,用于海量数据管理,核心特点包括:

高可靠性与扩展性‌:支持 99.9999999999% 数据可靠性,可存储任意类型文件(如图片、视频),容量无上限。‌
应用场景‌:
大数据分析:作为数据湖底座,支持 AI 训练和实时处理。‌
企业备份:提供端到端加密和跨区域灾备,降低数据丢失风险。‌
成本优化‌:提供 5 种存储类型(如标准型、低频访问型),按使用量付费,生命周期管理可降本 30%。‌

2.使用目的

服务器带宽为3MB,前端小程序加载图片显示速度较慢,升级带宽费用较高,使用阿里云OSS服务可以提高加载速度,并且可以根据用户id(user_id)单独建立一个文件夹,用来根据用户id分类存储,方便简洁

3.使用效果

微信小程序加载图片的速度变快,文件结构更加清晰

4.为什么速度变快

  • a: 就近访问:结合CDN/传输加速,把数据缓存到离用户最近的节点,不用跨远路取数据;
  • b. 热点缓存:高频访问的热数据会存在高速存储(如SSD)或本地缓存里,读取更高效;
  • c. 分布式架构:数据分散存储,避免请求扎堆拥堵,高并发下也能稳定快速响应。

5.如何使用

  1. 前端:请求后端获取 OSS 凭证 → 选择图片 → 压缩图片 → 调用uploadToOss上传到 OSS → 得到 OSS 文件 URL。
  2. 后端:提供getOssPolicy接口生成凭证 → 业务接口接收前端提交的 OSS URL 并存储。

一、后端(Node.js)核心代码

1. 配置文件(config/oss.js

javascript

运行

// 阿里云OSS配置
module.exports = {
  region: "你的OSS区域(如oss-cn-hangzhou)",
  accessKeyId: "你的AccessKeyId",
  accessKeySecret: "你的AccessKeySecret",
  bucket: "你的Bucket名称",
  host: "xxx", // 你的OSS自定义域名
  maxSize: 10 * 1024 * 1024, // 最大上传大小(10MB)
  expires: 3600, // Policy过期时间(秒)
};

2. OSS 凭证接口(controller/ossController.js

javascript

运行

const OSS = require("ali-oss");
const ossConfig = require("../config/oss");

// 获取OSS上传凭证(Policy)
exports.getOssPolicy = async (req, res) => {
  try {
    const { user_id } = req.query;
    if (!user_id) {
      return res.status(400).json({ code: 400, message: "缺少user_id" });
    }

    // 初始化OSS客户端
    const client = new OSS({
      region: ossConfig.region,
      accessKeyId: ossConfig.accessKeyId,
      accessKeySecret: ossConfig.accessKeySecret,
      bucket: ossConfig.bucket,
    });

    // 生成上传路径前缀(按用户隔离)
    const dir = `uploads/${user_id}/`;

    // 生成Policy
    const policy = client.calculatePostPolicy(
      {
        expiration: new Date(Date.now() + ossConfig.expires * 1000),
        conditions: [
          ["content-length-range", 0, ossConfig.maxSize], // 限制文件大小
          ["starts-with", "$key", dir], // 限制上传路径
        ],
      },
      {
        accessKeyId: ossConfig.accessKeyId,
        accessKeySecret: ossConfig.accessKeySecret,
      }
    );

    // 返回凭证给前端
    res.json({
      code: 200,
      data: {
        accessKeyId: ossConfig.accessKeyId,
        policy: policy.policy,
        signature: policy.signature,
        host: ossConfig.host,
        dir: dir,
      },
    });
  } catch (err) {
    console.error("获取OSS凭证失败:", err);
    res.status(500).json({ code: 500, message: "获取上传凭证失败" });
  }
};

3. 路由配置(router/ossRouter.js

javascript

运行

const express = require("express");
const router = express.Router();
const ossController = require("../controller/ossController");

// 获取OSS上传凭证
router.get("/getOssPolicy", ossController.getOssPolicy);

module.exports = router;

二、前端(微信小程序)核心代码

1. OSS 上传工具函数(utils/util.js

javascript

运行

/**
 * 上传文件到阿里云OSS
 * @param {string} filePath - 本地文件临时路径
 * @param {object} ossPolicy - 后端返回的OSS凭证
 * @returns {Promise<string>} - OSS文件URL
 */
export const uploadToOss = (filePath, ossPolicy) => {
  return new Promise((resolve, reject) => {
    // 生成唯一文件路径(避免覆盖)
    const fileName = filePath.substr(filePath.lastIndexOf("/") + 1);
    const key = `${ossPolicy.dir}${Date.now()}-${fileName}`;

    // 调用微信上传接口
    wx.uploadFile({
      url: ossPolicy.host,
      filePath: filePath,
      name: "file",
      formData: {
        key: key,
        policy: ossPolicy.policy,
        OSSAccessKeyId: ossPolicy.accessKeyId,
        signature: ossPolicy.signature,
      },
      success: (res) => {
        if (res.statusCode === 204) {
          const ossUrl = `${ossPolicy.host}/${key}`;
          resolve(ossUrl);
        } else {
          reject(new Error("OSS上传失败"));
        }
      },
      fail: (err) => reject(err),
    });
  });
};

// 图片压缩(可选)
export const compressImage = (filePath) => {
  return new Promise((resolve, reject) => {
    wx.compressImage({
      src: filePath,
      quality: 80,
      success: (res) => resolve(res.tempFilePath),
      fail: (err) => reject(err),
    });
  });
};

2. 页面上传逻辑(pages/publish/publish.js

javascript

运行

const app = getApp();
import { compressImage, uploadToOss } from "../../utils/util.js";

Page({
  data: {
    goodsImgs: [], // 存储图片:{localPath, serverUrl}
    user_id: "",
  },

  onLoad() {
    // 初始化用户ID
    this.setData({ user_id: app.globalData.userInfo.id });
  },

  // 选择并上传图片
  async chooseImage() {
    try {
      // 1. 获取OSS凭证
      const policyRes = await app.get("/goodsOss/getOssPolicy", {
        user_id: this.data.user_id,
      });
      if (policyRes.code !== 200) throw new Error("获取凭证失败");
      const ossPolicy = policyRes.data;

      // 2. 选择图片
      const chooseRes = await wx.chooseImage({
        count: 5,
        sizeType: ["compressed"],
      });
      const tempFilePaths = chooseRes.tempFilePaths;

      // 3. 循环上传
      for (let i = 0; i < tempFilePaths.length; i++) {
        const compressedPath = await compressImage(tempFilePaths[i]);
        const ossUrl = await uploadToOss(compressedPath, ossPolicy);

        // 更新图片列表
        this.setData({
          goodsImgs: [
            ...this.data.goodsImgs,
            { localPath: tempFilePaths[i], serverUrl: ossUrl },
          ],
        });
      }
      wx.showToast({ title: "上传成功" });
    } catch (err) {
      wx.showToast({ title: "上传失败", icon: "none" });
    }
  },

  // 发布商品(将OSS图片URL提交到后端)
  async publish() {
    const serverImgs = this.data.goodsImgs.map((img) => img.serverUrl);
    const res = await app.post("/goods/publish", {
      imgs: serverImgs.join(","),
      // 其他商品信息...
    });
    if (res.code === 200) wx.showToast({ title: "发布成功" });
  },
});

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注