介绍
在后端开发中,对象存储(OSS) 是文件存储、图片 / 视频托管、静态资源分发的核心组件。市面上成熟的 OSS(阿里云 OSS、腾讯云 COS)功能强大但成本较高,小型项目、私有部署场景下,我们更需要轻量、高性能、可自主掌控的私有对象存储。
如果你想搭建一套轻量、高性能、无依赖的私有对象存储(OSS),但不想从零写 Rust 服务,那 RustFS + Node.js 就是完美组合:
- RustFS:用 Rust 实现的轻量级对象存储服务,开箱即用,性能拉满
- Node.js:快速封装 RESTful API,对接 RustFS,适配业务场景
什么是 RustFS?
RustFS 是一个用 Rust 编写的轻量级对象存储服务,兼容 S3 协议,支持:
- 高性能文件读写
- 多端口服务(默认 9000 为 API 端口,9001 为控制台 / 管理端口)
- 兼容 S3 API,可直接用 S3 SDK 对接
- 支持本地文件系统存储,无需额外数据库
整体架构设计
bash
前端/客户端
↓
Node.js 服务(egg)
↓
RustFS 服务(端口 9000)
↓
本地文件系统(物理存储)
核心优势:
- 快速部署:RustFS 容器一键启动,无需配置
- 高性能:Rust 底层 IO,比 Node.js 原生文件操作快数倍
- 兼容 S3:可直接用 AWS SDK 或 S3 客户端对接
- 易扩展:Node.js 层可轻松封装权限控制、文件处理、元数据管理
安装RustFS容器
这里是用的宝塔面板,先安装docker 在dcoker下面安装 RustFs容器



oss对象存储面板


egg接入OSS对象存储
安装 minio
bash
npm i minio
oss配置
bash
config.rustfs = {
endPoint: '', // 你的服务器IP
port: 9001, // S3 API 端口(必须是 9001,不是控制台 9000)
useSSL: false,
accessKey: '',
secretKey: '',
bucket: '', // 你的桶名
externalUrl: 'http://xxx.xx.xx:9001', // 外网访问地址
};
上传和删除
在使用的地方就可以调用上传(uploadByStream)和删除(deleteFile)的方法
bash
'use strict';
const Service = require('egg').Service;
const { v4: uuidv4 } = require('uuid');
const Minio = require('minio');
class RustfsService extends Service {
constructor(ctx) {
super(ctx);
// 初始化客户端
const config = this.app.config.rustfs;
this.minioClient = new Minio.Client({
endPoint: config.endPoint,
port: Number(config.port),
useSSL: config.useSSL,
accessKey: config.accessKey,
secretKey: config.secretKey,
});
this.bucket = config.bucket;
this.externalUrl = config.externalUrl;
}
/**
* 流式上传
* @param {Stream} fileStream - 文件可读流
* @param {String} fileExt - 文件扩展名
* @param {String} [contentType='application/octet-stream'] - 文件类型
* @return {Object} 上传结果
*/
async uploadByStream(fileStream, fileExt, contentType = 'application/octet-stream') {
// 生成唯一文件 key
const fileName = `${uuidv4()}${fileExt}`;
const fileKey = `upload/${new Date().getFullYear()}_${new Date().getMonth() + 1}_${fileName}`;
try {
// 流式上传
const etag = await this.minioClient.putObject(
this.bucket,
fileKey,
fileStream,
{
'Content-Type': contentType,
}
);
return {
success: true,
key: fileKey,
url: `${this.externalUrl}/${this.bucket}/${fileKey}`,
hash: etag.etag,
fileKey,
};
} catch (error) {
this.ctx.logger.error('RustFS 流式上传失败:', error);
return {
success: false,
message: error.message,
};
}
}
/**
* 删除文件
* @param {String} fileKey - 文件key
* @return {Object} 删除结果
*/
async deleteFile(fileKey) {
console.log('fileKey', fileKey);
if (!fileKey) {
return {
success: false,
message: '文件key不能为空',
};
}
try {
await this.minioClient.removeObject(this.bucket, fileKey);
return {
success: true,
message: '文件删除成功',
fileKey,
};
} catch (error) {
this.ctx.logger.error('RustFS 文件删除失败:', error);
return {
success: false,
message: `删除失败:${error.message}`,
fileKey,
};
}
}
}
module.exports = RustfsService;