BugFree.FileStorage
1.2.2026.623-beta1157
This is a prerelease version of BugFree.FileStorage.
dotnet add package BugFree.FileStorage --version 1.2.2026.623-beta1157
NuGet\Install-Package BugFree.FileStorage -Version 1.2.2026.623-beta1157
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BugFree.FileStorage" Version="1.2.2026.623-beta1157" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BugFree.FileStorage" Version="1.2.2026.623-beta1157" />
<PackageReference Include="BugFree.FileStorage" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BugFree.FileStorage --version 1.2.2026.623-beta1157
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: BugFree.FileStorage, 1.2.2026.623-beta1157"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BugFree.FileStorage@1.2.2026.623-beta1157
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BugFree.FileStorage&version=1.2.2026.623-beta1157&prerelease
#tool nuget:?package=BugFree.FileStorage&version=1.2.2026.623-beta1157&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
BugFree.FileStorage
一个面向 .NET 的通用文件存储库,统一封装阿里云 OSS、腾讯云 COS、MinIO 和本地文件系统的对象存储能力。
✨ 核心特性
- 多 Provider 统一 API — 通过
FileStorageService统一操作 OSS / COS / MinIO / 本地文件系统,切换存储后端只需修改配置 - 分片上传 — 支持大文件分片上传(Initiate → UploadPart → Complete),内置并发控制与序号校验
- 预签名 URL — 为云端 Provider 生成可访问的预签名 URL,本地 Provider 返回安全签名参数(HMAC 验证,避免路径泄露)
- 智能磁盘选择 — 本地存储支持多磁盘/多根路径,可选顺序、剩余空间优先、随机策略
- 本地索引 — 支持落盘索引(FileIndex)和字符串索引(StringIndex),加速 bucket+key → disk 映射,自动修复脏索引
- 多目标框架 — 支持 .NET 8.0 和 .NET 10.0
- 配置驱动 — 集成 NewLife.Configuration,支持加密存储、热重载
📦 安装
dotnet add package BugFree.FileStorage
🚀 快速开始
1. 注册服务
builder.Services.AddFileStorageService();
2. 配置存储(appsettings.json)
{
"FileStorage": {
"ProviderType": "Minio",
"SingleFileMaxSize": 209715200,
"AliyunOss": {
"Endpoint": "oss-cn-hangzhou.aliyuncs.com",
"AccessKeyId": "<your-access-key-id>",
"AccessKeySecret": "<your-access-key-secret>",
"BucketName": "my-bucket"
},
"TencentCos": {
"SecretId": "<your-secret-id>",
"SecretKey": "<your-secret-key>",
"BucketName": "my-bucket-1234567890",
"Region": "ap-guangzhou"
},
"Minio": {
"Endpoint": "192.168.1.100:9000",
"AccessKey": "minioadmin",
"SecretKey": "minioadmin",
"BucketName": "my-bucket",
"EnableHttps": false
},
"Local": {
"StoragePath": ["D:\\FileStorage", "E:\\FileStorage"],
"SelectPolicy": "FreeSpaceFirst",
"SignedUrlExpireSeconds": 3600,
"FileIndexType": "String"
}
}
}
3. 使用
[ApiController]
public class FileController : ControllerBase
{
private readonly FileStorageService _fileStorage;
public FileController(FileStorageService fileStorage)
{
_fileStorage = fileStorage;
}
// 上传文件
[HttpPost("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
using var stream = file.OpenReadStream();
var info = await _fileStorage.UploadAsync(file.FileName, stream, file.Length, file.ContentType);
return Ok(info);
}
// 下载文件
[HttpGet("download/{bucket}/{key}")]
public async Task<IActionResult> Download(string bucket, string key)
{
var stream = await _fileStorage.GetAsync(StorageProviderType.Minio, bucket, key);
if (stream == null) return NotFound();
return File(stream, "application/octet-stream");
}
// 生成预签名 URL
[HttpGet("presigned/{bucket}/{key}")]
public async Task<IActionResult> Presigned(string bucket, string key)
{
var result = await _fileStorage.GeneratePresignedUrlAsync(StorageProviderType.Minio, bucket, key, TimeSpan.FromHours(1));
return Ok(result);
}
// 删除文件
[HttpDelete("delete/{bucket}/{key}")]
public async Task<IActionResult> Delete(string bucket, string key)
{
await _fileStorage.DeleteAsync(StorageProviderType.Minio, bucket, key);
return Ok();
}
}
4. 分片上传大文件
// 初始化分片
var context = await _fileStorage.InitiateMultipartUploadAsync("my-bucket", "large-file.bin");
// 分片上传(每个分片独立处理)
for (int i = 0; i < chunks.Length; i++)
{
using var stream = new MemoryStream(chunks[i]);
var result = await _fileStorage.UploadPartAsync(context, i + 1, stream, chunks[i].Length);
}
// 完成分片上传
var info = await _fileStorage.CompleteMultipartUploadAsync(context, results);
📂 项目结构
BugFree.FileStorage/
├── BugFree.FileStorage/ # 核心库
│ ├── Abstractions/ # 抽象定义
│ │ ├── IFileStorageProvider.cs # Provider 内部抽象
│ │ ├── FileObjectInfo.cs # 文件对象信息
│ │ ├── PresignedUrlResult.cs # 预签名结果
│ │ └── MultipartUploadContext.cs # 分片上传上下文
│ ├── Provider/ # 存储实现
│ │ ├── AliCloud/AliyunOssFileStorageProvider.cs # 阿里云 OSS
│ │ ├── TencentCloud/TencentCosFileStorageProvider.cs # 腾讯云 COS
│ │ ├── Minio/MinioFileStorageProvider.cs # MinIO
│ │ └── Local/ # 本地文件系统
│ │ ├── LocalFileStorageProvider.cs
│ │ ├── LocalFileStorageSetting.cs
│ │ ├── DiskSelector/ # 磁盘选择策略
│ │ │ ├── LocalDiskSelectorBase.cs
│ │ │ ├── SequentialDiskSelector.cs
│ │ │ ├── FreeSpaceFirstDiskSelector.cs
│ │ │ └── RandomDiskSelector.cs
│ │ └── Index/ # 索引实现
│ │ ├── IIndex.cs
│ │ ├── FileIndex.cs
│ │ └── StringIndex.cs
│ ├── FileStorageService.cs # 统一入口
│ ├── FileStorageSetting.cs # 配置
│ ├── StorageProviderType.cs # 枚举
│ └── ServiceCollectionExtensions.cs # DI 注册
├── BugFree.FileStorage.TestProject/ # 单元测试
├── Directory.Build.props # 全局 MSBuild 属性
└── Directory.Build.targets # 全局 MSBuild 目标
🔧 配置详解
全局配置
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ProviderType |
StorageProviderType |
Local |
存储类型 |
SingleFileMaxSize |
Int64 |
200MB | 单文件直接上传上限,超过需分片 |
MultipartSize |
Int32 |
64MB | 分片上传最小分片大小 |
MultipartConcurrency |
int |
4 | 分片上传最大并发数 |
MultipartMaxCount |
int |
200 | 分片上传最大分片数 |
本地存储
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
StoragePath |
IList<string> |
— | 存储根路径列表 |
SelectPolicy |
DiskSelectPolicy |
FreeSpaceFirst |
磁盘选择策略 |
SignedUrlExpireSeconds |
Int32 |
3600 | 预签名 URL 有效期(秒) |
FileIndexType |
FileIndexType |
String |
文件索引类型 |
ParamEncryptKey |
string |
随机 | 签名加密密钥 |
磁盘选择策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
Sequential |
按配置顺序循环选择 | 磁盘空间均匀分配 |
FreeSpaceFirst |
选择剩余空间最大的磁盘(默认) | 通用场景 |
Random |
随机选择 | 负载均衡,分散 I/O |
索引类型
| 类型 | 说明 | 特点 |
|---|---|---|
File |
落盘索引(文件存储) | 快速定位,进程重启可恢复 |
String |
字符串索引(diskId 嵌入 bucket) | 不落盘,零维护 |
🛡️ 安全设计
- 路径安全 — 上传和删除时使用
PathSecurityHelper校验 bucket/key,防止路径穿越攻击 - 预签名安全 — 本地存储使用 HMAC-MD5 签名(
{bucket}:{key}:{expireAt}),避免泄露真实本地路径 - 文件唯一性 — 上传使用
CreateNew模式,防止同名文件被意外覆盖 - 内容长度校验 — 对可 Seek 流强校验 contentLength,避免截断或合并异常
📝 本地存储预签名流程
本地存储不直接返回可访问 URL,采用签名参数模式:
1. 生成签名: {bucket}:{key}:{expireAtUnixSeconds} → HMAC-MD5 → sign
2. 返回 Query: { expireAt, sign }
3. 客户端请求: GET /api/download/{bucket}/{key}?expireAt=xxx&sign=xxx
4. 服务端验证: 检查 expireAt 未过期 + HMAC 签名匹配
5. 验证通过: 读取本地文件并返回
🧪 测试
cd BugFree.FileStorage.TestProject
dotnet test
📄 License
MIT License — Copyright (c) 2024 IoTHub 开发团队
🌐 English
See README.en.md for the English version.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- AlibabaCloud.OSS.V2 (>= 0.1.2)
- BugFree.Configuration (>= 1.2.2026.616-beta0953)
- Microsoft.Extensions.Options (>= 10.0.9)
- Tencent.QCloud.Cos.Sdk (>= 5.4.51)
-
net8.0
- AlibabaCloud.OSS.V2 (>= 0.1.2)
- BugFree.Configuration (>= 1.2.2026.616-beta0953)
- Microsoft.Extensions.Options (>= 10.0.9)
- Tencent.QCloud.Cos.Sdk (>= 5.4.51)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.2026.623-beta1157 | 40 | 6/23/2026 |
| 1.1.2026.325-beta1128 | 78 | 3/25/2026 |
| 1.1.2026.325-beta1042 | 53 | 3/25/2026 |
| 1.1.2026.325-beta1036 | 52 | 3/25/2026 |
| 1.1.2026.325-beta1013 | 57 | 3/25/2026 |
| 1.1.2026.303-beta1510 | 66 | 3/3/2026 |
| 1.1.2026.127-beta1557 | 70 | 3/3/2026 |
| 1.1.2026.115-beta1541 | 85 | 1/15/2026 |
| 1.0.2026.107-beta1426 | 77 | 1/7/2026 |
| 1.0.2026.106-beta1144 | 74 | 1/6/2026 |
| 1.0.2025.1224-beta1658 | 155 | 12/24/2025 |
| 1.0.2025.1224-beta1527 | 150 | 12/24/2025 |
| 1.0.2025.1224-beta1412 | 157 | 12/24/2025 |