RustFS 实现对象存储前端直传的超详细教程!

RustFS vs MinIO:轻量级对象存储对比与开发环境选型实践 在开发测试与日志观测场景中,对象存储作为数据持久化的核心组件,其轻量化部署能力直接影响资源利用效率。S3兼容接口已成为事实标准,让应用可以无缝对接不同实现。RustFS凭借Rust语言特性,以单二进制、几十MB内存占用实现极简部署,而MinIO依托Go生态提供成熟控制台、完善权限模型及丰富排障资料。本文深入对比两者在二进制大小、内存占用、API兼容、功能深度及部署便捷性上的差异,并结合Loki日志链路、前端直传、预签名URL等典型实践,呈现从概念原理到应用场景的完整技术画像。针对资源紧张或追求极简的团队,R 阅读详情

本文分享 RustFS 对象存储前段直传的完整实现方式,改变了传统的浏览器-> 后端服务器 -> 对象存储的上传方式,提高了效率和安全性。文章包括 5 个部分:

  • 前言
  • 核心概念
  • 两种方案详解
  • 技术实现
  • 完整示例
  • 最佳实践

什么是前端直传?

传统的文件上传流程:浏览器 → 后端服务器 → 对象存储这种方式存在以下问题:

  • 占用后端服务器带宽和资源
  • 上传速度受限于后端服务器
  • 需要处理大文件的内存管理
  • 服务器成本增加

前端直传则是:浏览器 → 对象存储

优势:

  • ✅ 减轻后端服务器压力
  • ✅ 上传速度更快(直连对象存储)
  • ✅ 降低服务器成本
  • ✅ 支持大文件上传

安全性问题

直传面临的核心问题:如何在不暴露永久密钥的情况下,让前端安全地上传文件?本教程介绍两种解决方案:

  1. 预签名 URL 方案(推荐)
  2. STS 临时凭证方案

对象存储基础

对象存储使用类似 AWS S3 的模型:

存储桶 (Bucket)
└── 对象 (Object)
    ├── Key: "uploads/photo.jpg"  # 对象路径
    ├── Value: [文件内容]
    └── Metadata: {ContentType, Size, etc.}

访问控制

对象存储通过 Access Key 和 Secret Key 进行身份验证:

永久密钥(长期有效,不应暴露给前端)
├── Access Key ID: "user-2"
└── Secret Access Key: "rustfsadmin"

临时凭证(短期有效,可以给前端使用)
├── Access Key ID
├── Secret Access Key
└── Session Token

两种方案详解

方案一:预签名 URL 方案(推荐)

适用场景

  • 单文件上传
  • 表单提交时附带文件
  • 简单安全的上传需求交
互流程
浏览器                    后端服务                   RustFS
  │                          │                          │
  │ ①请求预签名URL            │                          │
  ├──────────────────────────>│                          │
  │                          │                          │
  │                          │ ②使用boto3生成签名URL     │
  │                          │                          │
  │ ③返回预签名URL            │                          │
  │<──────────────────────────┤                          │
  │                          │                          │
  │ ④使用预签名URL直传文件                               │
  ├─────────────────────────────────────────────────────>│
  │                          │                          │
  │ ⑤返回成功                                            │
  │<──────────────────────────────────────────────────────┤

优势:

  • 前端实现极简,无需处理签名
  • 后端完全控制权限
  • 无需额外依赖
  • 每个文件独立权限控制

方案二:STS 临时凭证方案

推荐场景:

  • 批量文件上传(如相册上传)
  • 长时间上传操作
  • 需要多次上传的场景
交互流程
浏览器                    后端服务                   RustFS
  │                          │                          │
  │ ①请求临时凭证              │                          │
  ├──────────────────────────>│                          │
  │                          │                          │
  │ ②返回临时凭证              │                          │
  │<──────────────────────────┤                          │
  │                          │                          │
  │ ③前端使用SDK上传(凭证可复用)                        │
  ├─────────────────────────────────────────────────────>│
  │                          │                          │
  │ ④继续上传其他文件                                     │
  ├─────────────────────────────────────────────────────>│

优势

  • 凭证可复用,减少网络请求
  • 适合批量上传
  • 灵活控制权限

技术实现

后端实现(使用 boto3)

  • 安装依赖
pip install boto3 flask flask-cors
  • 核心代码
import boto3
from botocore.client import Config
from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# 配置
RUSTFS_CONFIG = {
    'access_key_id': 'user-2',
    'secret_access_key': 'rustfsadmin',
    'endpoint_url': 'http://127.0.0.1:9000',
    'bucket_name': 'test-bucket',
    'region_name': 'us-east-1'
}

def create_s3_client():
    """创建 S3 客户端"""
    return boto3.client(
        's3',
        aws_access_key_id=RUSTFS_CONFIG['access_key_id'],
        aws_secret_access_key=RUSTFS_CONFIG['secret_access_key'],
        endpoint_url=RUSTFS_CONFIG['endpoint_url'],
        region_name=RUSTFS_CONFIG['region_name'],
        config=Config(
            signature_version='s3v4',
            s3={'addressing_style': 'path'}
        )
    )

# 方案一:预签名 URL
@app.route('/api/presigned-url', methods=['POST'])
def get_presigned_url():
    """生成预签名 URL"""
    data = request.get_json()
    object_key = data['object_key']
    content_type = data.get('content_type', 'application/octet-stream')
    expires = data.get('expires', 3600)

    s3_client = create_s3_client()

    # boto3 自动处理签名
    presigned_url = s3_client.generate_presigned_url(
        ClientMethod='put_object',
        Params={
            'Bucket': RUSTFS_CONFIG['bucket_name'],
            'Key': object_key,
            'ContentType': content_type
        },
        ExpiresIn=expires
    )

    return jsonify({
        'code': 0,
        'data': {
            'url': presigned_url,
            'method': 'PUT',
            'headers': {'Content-Type': content_type}
        }
    })

# 方案二:STS 临时凭证
@app.route('/api/sts/credentials', methods=['POST'])
def get_sts_credentials():
    """获取 S3 临时凭证"""
    # 生产环境应该使用真实的 STS AssumeRole
    # sts_client = boto3.client('sts')
    # response = sts_client.assume_role(...)

    return jsonify({
        'code': 0,
        'data': {
            'access_key_id': RUSTFS_CONFIG['access_key_id'],
            'secret_access_key': RUSTFS_CONFIG['secret_access_key'],
            'endpoint_url': RUSTFS_CONFIG['endpoint_url'],
            'bucket_name': RUSTFS_CONFIG['bucket_name'],
            'region_name': RUSTFS_CONFIG['region_name']
        }
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

前端实现(使用 @aws-sdk/client-s3)

  • 安装依赖
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner vue
  • 方案一:预签名 URL
上传// utils/upload-presigned.ts

/**
 * 使用预签名 URL 上传文件
 */
exportasyncfunction uploadWithPresignedUrl(
  file: File,
  objectKey: string,
  onProgress?: (progress: number) => void
): Promise<string> {
// 1. 获取预签名 URL
const response = await fetch('http://127.0.0.1:9000/api/presigned-url', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      object_key: objectKey,
      content_type: file.type
    })
  })
const { data } = await response.json()

// 2. 使用预签名 URL 上传
returnnewPromise((resolve, reject) => {
    const xhr = new XMLHttpRequest()

    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable && onProgress) {
        onProgress(Math.round((e.loaded / e.total) * 100))
      }
    })

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(data.url.split('?')[0])
      } else {
        reject(newError(`上传失败: ${xhr.status}`))
      }
    })

    xhr.addEventListener('error', () => reject(newError('网络错误')))

    xhr.open(data.method, data.url, true)
    Object.entries(data.headers).forEach(([key, value]) => {
      xhr.setRequestHeader(key, value asstring)
    })
    xhr.send(file)
  })
}
  • 方案二:STS 凭证
上传/ utils/upload-sdk.ts

import { S3Client, PutObjectCommand } from'@aws-sdk/client-s3'
import { getSignedUrl } from'@aws-sdk/s3-request-presigner'

interface S3Credentials {
  access_key_id: string
  secret_access_key: string
  endpoint_url: string
  bucket_name: string
  region_name: string
}

/**
 * 使用 AWS SDK 上传文件(带进度)
 */
exportasyncfunction uploadWithSDK(
  file: File,
  objectKey: string,
  credentials: S3Credentials,
  onProgress?: (progress: number) => void
): Promise<string> {
// 1. 创建 S3 客户端
const s3Client = new S3Client({
    credentials: {
      accessKeyId: credentials.access_key_id,
      secretAccessKey: credentials.secret_access_key
    },
    endpoint: credentials.endpoint_url,
    region: credentials.region_name,
    forcePathStyle: true
  })

// 2. 如果需要进度,使用预签名 URL + XHR
if (onProgress) {
    const command = new PutObjectCommand({
      Bucket: credentials.bucket_name,
      Key: objectKey,
      ContentType: file.type
    })

    const presignedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 })

    returnnewPromise((resolve, reject) => {
      const xhr = new XMLHttpRequest()

      xhr.upload.addEventListener('progress', (e) => {
        if (e.lengthComputable) {
          onProgress(Math.round((e.loaded / e.total) * 100))
        }
      })

      xhr.addEventListener('load', () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(`${credentials.endpoint_url}/${credentials.bucket_name}/${objectKey}`)
        } else {
          reject(newError(`上传失败: ${xhr.status}`))
        }
      })

      xhr.addEventListener('error', () => reject(newError('网络错误')))

      xhr.open('PUT', presignedUrl, true)
      xhr.setRequestHeader('Content-Type', file.type)
      xhr.send(file)
    })
  }

// 3. 简单上传(无进度)
const command = new PutObjectCommand({
    Bucket: credentials.bucket_name,
    Key: objectKey,
    Body: file,
    ContentType: file.type
  })

await s3Client.send(command)
return`${credentials.endpoint_url}/${credentials.bucket_name}/${objectKey}`
}

/**
 * 获取 S3 凭证
 */
exportasyncfunction getS3Credentials(): Promise<S3Credentials> {
const response = await fetch('http://127.0.0.1:9000/api/sts/credentials', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' }
  })
const { data } = await response.json()
return data
}

/**
 * 生成唯一的对象路径
 */
exportfunction generateObjectKey(file: File, prefix = 'uploads'): string {
const timestamp = Date.now()
const random = Math.random().toString(36).substring(2, 8)
const ext = file.name.split('.').pop() || ''
return`${prefix}/${timestamp}_${random}.${ext}`
}

Vue 组件示例

<template>
  <div class="upload-container">
    <h2>文件上传</h2>

    <div class="upload-area" @click="$refs.fileInput.click()">
      <input
        ref="fileInput"
        type="file"
        multiple
        style="display: none"
        @change="handleFileSelect"
      />
      <p>点击选择文件上传</p>
    </div>

    <div v-for="file in files" :key="file.id" class="file-item">
      <span>{{ file.name }}</span>
      <div v-if="file.status === 'uploading'">
        <progress :value="file.progress" max="100"></progress>
        <span>{{ file.progress }}%</span>
      </div>
      <span v-else-if="file.status === 'success'">✅ 成功</span>
      <span v-else-if="file.status === 'error'">❌ {{ file.error }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { uploadWithPresignedUrl, generateObjectKey } from '../utils/upload-presigned'
// 或者使用: import { uploadWithSDK, getS3Credentials } from '../utils/upload-sdk'

interface UploadFile {
  id: string
  name: string
  status: 'pending' | 'uploading' | 'success' | 'error'
  progress: number
  error?: string
}

const files = ref<UploadFile[]>([])

const handleFileSelect = (event: Event) => {
  const target = event.target as HTMLInputElement
  if (!target.files) return

  Array.from(target.files).forEach((file) => {
    const uploadFile: UploadFile = {
      id: `${Date.now()}_${Math.random()}`,
      name: file.name,
      status: 'pending',
      progress: 0
    }
    files.value.push(uploadFile)
    startUpload(uploadFile, file)
  })

  target.value = ''
}

const startUpload = async (uploadFile: UploadFile, file: File) => {
  uploadFile.status = 'uploading'

  try {
    const objectKey = generateObjectKey(file)

    // 方案一:预签名 URL
    await uploadWithPresignedUrl(file, objectKey, (progress) => {
      uploadFile.progress = progress
    })

    // 方案二:STS 凭证(需要先获取凭证)
    // const credentials = await getS3Credentials()
    // await uploadWithSDK(file, objectKey, credentials, (progress) => {
    //   uploadFile.progress = progress
    // })

    uploadFile.status = 'success'
  } catch (error) {
    uploadFile.status = 'error'
    uploadFile.error = error instanceof Error ? error.message : '上传失败'
  }
}
</script>

<style scoped>
.upload-area {
  border: 2px dashed #ccc;
  padding: 40px;
  text-align: center;
  cursor: pointer;
}

.upload-area:hover {
  border-color: #666;
}

.file-item {
  padding: 10px;
  border-bottom: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

progress {
  width: 200px;
  margin: 0 10px;
}
</style>

完整示例

场景一:单文件上传(预签名 URL)

// 简单上传一个文件
const file = document.querySelector('input[type="file"]').files[0]
const objectKey = `uploads/${Date.now()}_${file.name}`

await uploadWithPresignedUrl(file, objectKey, (progress) => {
  console.log(`进度: ${progress}%`)
})

console.log('上传成功!')

场景二:批量上传(STS 凭证)

// 批量上传多个文件
const files = [...document.querySelector('input[type="file"]').files]

// 1. 获取一次凭证
const credentials = await getS3Credentials()

// 2. 使用同一凭证上传所有文件
awaitPromise.all(
  files.map((file) => {
    const objectKey = generateObjectKey(file)
    return uploadWithSDK(file, objectKey, credentials, (progress) => {
      console.log(`${file.name}: ${progress}%`)
    })
  })
)

console.log('全部上传成功!')

最佳实践

1. 方案选择

单文件或少量文件  →  预签名 URL(简单直接)
批量文件上传      →  STS 凭证(减少请求)
  1. 文件验证
function validateFile(file: File): boolean {
// 大小限制(100MB)
if (file.size > 100 * 1024 * 1024) {
    alert('文件过大')
    returnfalse
  }

// 类型限制
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
if (!allowedTypes.includes(file.type)) {
    alert('不支持的文件类型')
    returnfalse
  }

returntrue
}

  1. 错误处理和重试
async function uploadWithRetry(file: File, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
    try {
      const objectKey = generateObjectKey(file)
      returnawait uploadWithPresignedUrl(file, objectKey)
    } catch (error) {
      if (i === maxRetries - 1) throw error
      awaitnewPromise(resolve => setTimeout(resolve, 1000 * (i + 1)))
    }
  }
}
  1. 安全建议
# 后端验证
@app.route('/api/presigned-url', methods=['POST'])
def get_presigned_url():
    # ✅ 验证文件类型
    allowed_types = ['image/jpeg', 'image/png']
    if data['content_type'] notin allowed_types:
        return jsonify({'code': 400, 'message': '不支持的文件类型'}), 400

    # ✅ 验证用户权限
    # if not current_user.can_upload():
    #     return jsonify({'code': 403, 'message': '无权限'}), 403

    # ✅ 限制文件路径
    # 确保用户只能上传到自己的目录
    # object_key = f"users/{current_user.id}/{filename}"

    # 生成预签名 URL
    # ...
  1. 性能优化
// 并发控制:最多同时上传 3 个文件
asyncfunction uploadFilesWithLimit(files: File[], limit = 3) {
const queue = [...files]
const results = []
const executing = new Set()

while (queue.length > 0 || executing.size > 0) {
    while (queue.length > 0 && executing.size < limit) {
      const file = queue.shift()!
      const promise = uploadWithPresignedUrl(file, generateObjectKey(file))
        .then((url) => {
          executing.delete(promise)
          return { success: true, url }
        })
        .catch((error) => {
          executing.delete(promise)
          return { success: false, error }
        })

      executing.add(promise)
      results.push(promise)
    }

    if (executing.size > 0) {
      awaitPromise.race(executing)
    }
  }

returnPromise.all(results)
}

总结

核心要点

  1. ✅ 使用 AWS SDK - boto3(后端)和 @aws-sdk/client-s3(前端)
  2. ✅ 预签名 URL - 简单场景首选,后端完全控制
  3. ✅ STS 凭证 - 批量上传,减少网络请求
  4. ✅ 永久密钥不暴露 - 只在后端使用
  5. ✅ 添加验证 - 文件类型、大小、用户权限
  6. ✅ 错误处理 - 重试机制,友好提示两种方案对比

在这里插入图片描述

方案对比教程完成!开始构建你的文件上传功能吧! 🎉

RustFS入门使用-存储非结构化数据(图片、视频、日志文件等) 本文介绍了基于RustFS构建非结构化数据存储的完整方案。RustFS作为高性能分布式对象存储系统,具有轻量高效(100MB大小)、完全兼容S3、多架构支持等特点。文章详细讲解了Docker和二进制两种部署方式,并演示了图片、视频、日志等非结构化数据的具体存储方法,包括分片上传、生命周期管理等高级功能。同时提供了Python、Java、Node.js等语言的集成示例代码,涵盖文件上传、列举、预签名URL生成等常见操作。最后分享了数据加密、性能监控等最佳实践,帮助开发者构建安全高效的存储解决方案。 阅读详情

相关推荐

SpringBoot+RustFS保姆级教程!文件管理全场景实战,含分片上传企业级方案

本文介绍了如何利用SpringBoot+RustFS构建高性能文件存储系统。通过Docker或二进制方式快速部署RustFS,并详细展示了SpringBoot集成RustFS实现基础文件操作和企业级分片上传的完整方案。文章重点对比了RustFS与传统方案在性能(吞吐量提升43.6%)、成本(降低90%)等方面的优势,提供了分片上传的核心实现代码和性能优化建议(分片大小选择、并发控制等)。此外还涵盖安全权限管理、生产环境部署监控等企业级实践,最后总结了最佳实践方案,帮助开发者构建高可靠、高性能的文件存储服务。

分布式存储与RustFS的博客 2531

RustFS:MinIO的“平替”还是“乱杀”?

国产存储系统RustFS在性能上全面超越MinIO,4K随机读提升42%,内存占用降低67%。其采用Rust语言实现内存安全,Apache2.0协议规避AGPLv3风险,支持国产化适配和智能分层存储。虽然生态建设尚不完善,但100%兼容S3协议,在AI训练、边缘计算等场景优势显著。技术选型需权衡性能、稳定性和生态成熟度,RustFS适合追求极致性能的团队,MinIO则更符合稳定优先的需求。

分布式存储与RustFS的博客 2548

RustFS vs MinIO 单机版:开发测试环境对象存储选型实战

对象存储是现代应用的基础组件,但在开发测试环境中,直接使用云端服务往往显得笨重。S3兼容的轻量级单机方案成为本地联调、日志链路和微服务开发的首选。这类方案基于标准S3接口,提供对象存储的核心能力,同时将资源占用降到极低,让开发者可以在笔记本上快速搭建可丢弃的存储服务。在实际工程中,无论是指引Loki等日志系统接入,还是为前端直传生成预签名URL,单机对象存储都能显著提升迭代效率。从实践角度对比RustFS与MinIO单机版的部署体验、资源占用、S3兼容性及常见问题,帮助开发者在不同场景下做出合适选择。

weixin_29163857的博客 298

RustFS是国产的吗?有人用吗?

是国产的,符合信创要求。并且,RustFS 是与 Amazon S3 、阿里云OSS和腾讯云COS兼容的分布式对象存储服务器。它是完全中国自主知识产权,独立开发的,对标MinIO中间件平替的产品。RustFS是高性能分布式对象存储器服务器,专为大型专用云基础结构而设计。使用 Amazon S3 REST API 将持久卷 (PV) 聚集到可扩展的分布式对象存储器中。最适合用于存储非结构化数据,例如,照片、视频、日志文件、备份、VM 和容器映像。

kaiwenli的专栏 4436

RustFS 1.0.0:Rust重写的轻量级S3兼容对象存储,Minio替代方案

对象存储是现代应用的基础依赖,S3协议已成为事实标准,Minio凭借生态成熟被广泛使用,但其Go实现带来的内存占用高、配置复杂等问题,在中小团队和边缘场景中往往显得过重。RustFS 1.0.0以Rust重写核心,保持S3 API兼容,无GC、内存可控、镜像精简,让对象存储回归轻量本质。从上传下载、断点续传到预签名URL,RustFS覆盖常用链路,并能通过Docker快速部署,与Spring Boot、小程序、RAGFlow等场景无缝集成。本文从对象存储选型痛点切入,拆解RustFS的架构取舍、部署实践、生

weixin_33919950的博客 343

SpringBoot+RustFS构建云原生分布式文件存储系统实战

本文详细介绍了如何利用SpringBoot与RustFS构建高性能、云原生的分布式文件存储系统。通过Docker Compose快速部署RustFS,并重点讲解了SpringBoot应用如何优雅集成S3客户端,实现文件上传、下载及管理。文章还涵盖了生产环境配置调优、高可用集群搭建以及监控告警等进阶实践,为开发者提供了一套从零到一、具备弹性伸缩能力的完整解决方案。

weixin_29248611的博客 460

RustFS: 高性能分布式对象存储的优雅之选

RustFS 是一个高性能分布式对象存储系统,专为现代云原生应用设计。高性能:利用 Rust 的零成本抽象和高效内存管理,RustFS 在读写速度上表现卓越,适合处理从 100 TB 到 EB 级别的海量数据。S3 兼容性:完全兼容 AWS S3 协议,支持与现有 S3 应用无缝集成。分布式架构:支持 Kubernetes 原生部署,具备高可用性和容错能力,适合多云和边缘计算场景。开源与安全:基于 Apache 2.0 许可证,无知识产权风险,支持国产保密设备和系统。轻量级设计。

houseme的专栏 3064

RustFS 1.0.0 对比 MinIO:性能、迁移与踩坑全解析

对象存储作为海量非结构化数据的核心基础设施,其选型直接影响系统性能与运维成本。S3 API已成为事实标准,兼容性决定了生态迁移的平滑度。RustFS 1.0.0作为一款基于Rust语言的无GC对象存储,通过底层存储引擎优化实现了更低的资源占用与更稳定的延迟表现,在相同硬件条件下相比MinIO展现出约20%的吞吐提升。它单二进制、镜像体积小的特性,特别适合Docker部署与资源受限的云端环境。无论是新项目选型还是存量MinIO集群迁移,RustFS都提供了清晰的路径,但需注意事件通知等高级功能的差异。本文基于

weixin_33393017的博客 314

RustFs 前端开发

本文档详细介绍了如何在Node.js环境中使用AWS S3 JavaScript SDK(v3)连接RustFS对象存储系统。主要内容包括:SDK安装和初始化配置;基础操作(创建Bucket、上传/下载/删除/列举对象);高级功能(生成预签名URL、分片上传);常见问题解决方法。文档提供了完整的代码示例,特别强调需要启用forcePathStyle以兼容RustFS,并展示了如何在前端通过预签名URL实现安全上传。适用于开发者快速实现与RustFS的集成。

wangzhen12138的博客 554

MinIO无感切换RustFS:S3协议下的三行配置迁移实战

在分布式存储领域,S3协议已成为对象存储的事实标准,它像一层通用语言,将底层存储实现与上层业务解耦。理解这一协议原理,就能明白为什么更换存储服务时无需重写代码,只需调整endpoint、密钥等关键配置。基于S3协议的对象存储迁移,技术价值在于实现业务无感知的平滑切换,避免因存储维护而中断服务。在实际应用中,当MinIO面临版本升级、磁盘扩容或控制台异常时,利用兼容S3 API的RustFS作为替代方案,配合rclone与mc mirror进行数据在线同步,即可完成从旧存储到新存储的无缝过渡。本文从工程实践角

weixin_33461476的博客 135

FPGA之道(22)VHDL基本程序框架

在介绍详细的VHDL语法之前,让我们先来了解一下VHDL代码的基本程序框架,这样可以让我们先对VHDL程序设计有一个整体的概念把握,进而在后续的VHDL语法学习中做到有的放矢。

Reborn Lee 8309

Windows原生版RustFS:无需Docker,1分钟本地对象存储环境搭建

RustFS Windows原生版为开发者提供了一键搭建本地S3兼容对象存储的解决方案。其核心优势包括零依赖(无需Docker/WSL2)、1分钟快速部署、S3完全兼容、轻量高效(内存<100MB)和可视化控制台。适用于本地开发测试、小文件存储和学习场景,系统要求仅为Win10/11 64位+2核4GB内存。部署仅需下载35MB安装包、配置数据目录并启动服务,通过Web控制台(http://127.0.0.1:9001)即可管理。注意该版本仅支持单机模式,生产环境需使用Linux版本。

分布式存储与RustFS的博客 786

【电子元件篇】MOSFET场效应管作用、选型和测量指南-超简单解读

场效应管是一种电压控制型半导体器件,相比三极管具有输入阻抗高、噪声小、功耗低等优势。主要分为结型和绝缘栅型两大类,后者又可分为耗尽型和增强型MOS管。场效应管通过栅极电压控制漏极电流,具有转移特性和输出特性两大静态特性,以及快速的开关特性。其关键参数包括饱和漏源电流、夹断电压、跨导等,应用场景涵盖信号放大、恒流源、阻抗变换等领域。使用时需根据电路需求选择合适类型,如结型管适合一般放大,功率MOSFET适合高压大电流场合。检测时可用万用表电阻档初步判断好坏和放大能力。

2301_81299416的博客 2540

RustFS 预签名上传大小限制:用 SigV4 查询参数为浏览器直传 PutObject 与 Multipart 设置容量上限

RustFS 是开源、兼容 S3 的对象存储系统。当你的后端需要向浏览器签发 SigV4 预签名(presigned)上传 URL,但又必须限制单个 URL 允许上传的数据量时,可以通过两个 RustFS 专有的查询参数来达成:`x-rustfs-max-content-length`(单请求 `PutObject` 上限)与 `x-rustfs-max-total-object-size`(单个

gitblog_00282的博客 197

手把手教你用HiNet实现图像隐藏:可逆神经网络实战指南(附代码)

本文提供了一份基于HiNet框架实现图像隐藏的实战指南。通过详细解析可逆神经网络原理,手把手指导环境搭建、模型构建、损失函数设计及训练流程,并附有完整代码。该方法利用单个可逆网络统一隐藏与恢复过程,结合小波变换提升隐蔽性,为信息隐藏应用提供了高效解决方案。

rgv234567的博客 433

(11)(2.2.2) BLHeli32,AM32, and BLHeli_S ESCs(一)

Ardupilot官网关于《Peripheral Hardware》的翻译 —《(2.2.2) BLHeli32,AM32, and BLHeli_S ESCs》。

无人机开发(开源Ardupilot) 2231

RustFS 1.0 GA实测:它能否替代MinIO成为对象存储新选择?

在云原生与分布式架构快速演进的今天,对象存储作为海量非结构化数据的基座,其技术选型直接影响着应用的性能与运维成本。S3协议作为事实标准,其兼容性成为评估存储系统价值的关键维度。RustFS作为一颗新星,凭借Rust语言的安全并发特性与极致资源利用,在轻量部署和高吞吐场景下展现出显著优势。本文从基础的S3接口兼容性切入,深入剖析其存储引擎的底层原理与元数据管理机制,并基于Docker部署的实操经验,分别验证其在Spring Boot、x-file-storage等主流技术栈中的集成价值。通过客观对比RustF

weixin_31742871的博客 206

手把手教你学simulink(13.2)--构建一个单相并网逆变器Simulink仿真模型

基于Simulink的单相并网逆变器项目的详细仿真实例。这个项目将重点放在逆变器的详细建模、最大功率点跟踪(MPPT)控制策略、并网控制和仿真分析上。我们将使用MATLAB/Simulink来构建整个系统,并通过具体的代码和模块来实现各个功能。

MHD0815的博客 545

训练实验的模型文件别散落各处:用 RustFS 当 MLflow 的 artifact store

一次训练跑几百轮,模型权重、指标图、中间产物散落在每台机器的本地盘,换机器就找不回上次的实验。MLflow 把 artifact(产物文件)落到对象存储就能解决这个问题。RustFS 是 100% 兼容 S3 的存储,官方集成目录(docs.rustfs.com/zh/developer/integration)的 AI 类目里 MLflow 有专门的指南,用 Docker Compose 以 …

分布式存储与RustFS的博客 617

【yolo】YOLOv8模型导出完全指南:从PT到ONNX及其他格式的完整实践

摘要:本文全面介绍了YOLOv8模型从PT格式导出为ONNX等部署格式的完整流程与最佳实践。重点解析了关键参数(如format、imgsz、simplify)的作用机制,特别强调输入尺寸imgsz会自动继承训练尺寸的特性,并提供了ONNX、TensorRT等格式的典型导出配置方案。文章还总结了常见问题解决办法,推荐使用simplify优化模型性能,同时分享了通过C#实现模型重命名的实用技巧。最后指出"训练决定能力,导出定义接口"的核心原则,帮助开发者高效完成模型部署转换。

songhuangong123的博客 1917

全志V3S嵌入式驱动开发(驱动开发准备)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 之前的文章都是教大家怎么搭建环境、看原理图、编译内核和根文件系统、做镜像,直到现在才进入驱动开发的主题。毕竟整个专栏的目的,还是希望大家能够学会驱动外部硬件。驱动好硬件,分成硬件和软件两个部分,硬件的部分比较好理解,就是看相关的信号有没有对接上即可,但是软件对接、甚至于怎么写软件,大家好像接触的比较少,所以这个时候,就可以简单讨论一下,怎么样才能写驱动代码。 1、了解外部驱动芯

嵌入式-老费,一个分享专业嵌入式知识的blog 2025

从S3迁移到RustFS全指南:零成本实现数据主权,这些坑你别踩

本文提供了从AWS S3迁移至RustFS开源对象存储的完整实战指南。通过深度兼容性验证、生产级集群部署、数据迁移策略及权限重构,帮助企业以零成本实现数据主权,并规避迁移过程中的常见陷阱,最终构建高性能、可无限扩展的私有云存储方案。

weixin_29012765的博客 244

基于瑞芯微RK3562 四核 ARM Cortex-A53 + 单核 ARM Cortex-M0——Linux应用开发手册

本文主要介绍TL3562-MiniEVM评估板的AMP(Asymmetric Multi-processing)开发案例,介绍基于Linux + RT-Thread(RTOS)、Baremetal的AMP案例的开发环境搭建。

创龙,嵌入式一体化解决方案商 411

rustfs-io-metrics 指标与配置模块深度解析:RustFS 缓存、背压与 I/O 观测体系

rustfs-io-metrics 是 RustFS 分布式对象存储系统中所有指标(metrics)的统一采集与配置入口,负责缓存配置、自适应 TTL、访问追踪、带宽监控、I/O 调度与背压观测等核心可观测能力。本文基于 [crates/io-metrics/README_zh.md](https://link.gitcode.com/i/4bb834e88bfe646c70530989e5815

gitblog_01033的博客 922

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

RustFS 1.0 GA 深度解析:能否平替 MinIO 的对象存储选型指南

对象存储选型中,S3 兼容 API 是降低迁移成本的关键,而底层实现的语言特性直接影响资源占用与延迟表现。Rust 凭借无 GC 和内存安全等优势,在 IO 密集型场景中展现出更稳定的 P99 延迟和更低的内存开销。这种技术价值在边缘计算、资源受限环境及对延迟敏感的在线服务中尤为突出。RustFS 正是基于 Rust 构建的 S3 兼容分布式对象存储,本文围绕其 1.0.0 GA 版本,从架构取舍、性能对比、迁移实操到踩坑排查,系统分析它在中小规模场景下平替 MinIO 的可行性与边界。

weixin_30512965的博客 252

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

#国产存储新星RustFS横空出世!开源一周登顶GitHub热榜,网友:碾压MinIO

国产RustFS存储系统强势崛起:这款完全自主可控的分布式存储系统以93MB轻量化设计引发关注。采用Apache 2.0开源协议,完美适配信创生态,已获23家机构验证。性能表现亮眼:4K随机读达1.58M IOPS,较MinIO提升43.6%,支持树莓派到AI数据湖全场景。其极简部署(三条命令启动)、内置Web控制台等特性赢得开发者青睐,GitHub周增星735颗。尽管存在生产就绪度争议,但RustFS已展现出替代MinIO的潜力,成为信创替代浪潮中的新选择。

分布式存储与RustFS的博客 1244
上一篇: MinIO 开源官宣停服,开源用户该何去何从?
下一篇: 利用 RustFS + MLflow,打造 MLOps 平台的超详细教程
rustfs
博客等级 码龄1年 21粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值