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.如何使用
- 前端:请求后端获取 OSS 凭证 → 选择图片 → 压缩图片 → 调用
uploadToOss上传到 OSS → 得到 OSS 文件 URL。 - 后端:提供
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: "发布成功" });
},
});

发表回复