nodejs使用RustFS容器服务搭建对象存储oss

介绍

在后端开发中,对象存储(OSS) 是文件存储、图片 / 视频托管、静态资源分发的核心组件。市面上成熟的 OSS(阿里云 OSS、腾讯云 COS)功能强大但成本较高,小型项目、私有部署场景下,我们更需要轻量、高性能、可自主掌控的私有对象存储。

如果你想搭建一套轻量、高性能、无依赖的私有对象存储(OSS),但不想从零写 Rust 服务,那 RustFS + Node.js 就是完美组合:

  1. RustFS:用 Rust 实现的轻量级对象存储服务,开箱即用,性能拉满
  2. Node.js:快速封装 RESTful API,对接 RustFS,适配业务场景

什么是 RustFS?

RustFS 是一个用 Rust 编写的轻量级对象存储服务,兼容 S3 协议,支持:

  1. 高性能文件读写
  2. 多端口服务(默认 9000 为 API 端口,9001 为控制台 / 管理端口)
  3. 兼容 S3 API,可直接用 S3 SDK 对接
  4. 支持本地文件系统存储,无需额外数据库

整体架构设计

bash 复制代码
前端/客户端
    ↓
Node.js 服务(egg)
    ↓
RustFS 服务(端口 9000)
    ↓
本地文件系统(物理存储)

核心优势:

  1. 快速部署:RustFS 容器一键启动,无需配置
  2. 高性能:Rust 底层 IO,比 Node.js 原生文件操作快数倍
  3. 兼容 S3:可直接用 AWS SDK 或 S3 客户端对接
  4. 易扩展: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;
相关推荐
孟陬18 小时前
解决动态 import 类型 Any 痼癖
typescript·node.js·bun
Dumbness18 小时前
后台管理员把自己锁在门外:RBAC 里「自己的权限只能由别人来减」
安全·node.js
攻城狮白玉21 小时前
Node.js 发布紧急安全更新:10 个漏洞,8 枚危险证书被拉黑。附AI修复提示词
node.js
Json____1 天前
用 FastAPI + Vue3 打造一套完整的在线考试系统:从组卷到阅卷的业务闭环实践
后端·node.js·fastapi·it学习·wwwoop.com
Dumbness2 天前
写 MCP 服务器踩的坑:stdout 是协议通道,一行不带换行的日志就能让客户端超时
node.js·mcp
flash俊杰2 天前
ContentPart 联合类型实战:不碰存量消息,怎么给 ChatMessage 加图片
node.js
Json____2 天前
用 Node.js + Vue3 打造一个家居装修 AI 智能咨询助手
node.js·agent·网站开发·智能体·wwwoop.com
幸运小圣2 天前
fs 模块完全指南:文件读写、移动删除与文件夹操作(新手友好)【Node.js】
node.js·编辑器·vim
Dumbness3 天前
不发 npm 也能 npx:用 github: 协议分发一个零依赖 CLI
node.js
Patrick_Wilson3 天前
npm 的 bin 如何接到 npm run 与 npx
npm·node.js·前端工程化