在C#项目里实现兼容S3协议的对象存储文件上传,MinIO是常用的轻量解决方案,它完全兼容S3协议接口,部署和使用成本较低,适合各类规模的项目对接。

环境准备与依赖引入
首先需要在项目中引入MinIO的官方C# SDK,通过NuGet包管理器搜索Minio安装最新稳定版本即可。安装完成后,需要准备MinIO服务的连接信息,包括服务端点、访问密钥、秘密密钥以及存储桶名称。
客户端初始化配置
初始化MinIO客户端是上传文件的第一步,需要正确配置S3协议相关的连接参数,确保客户端能够正常对接MinIO服务。以下是客户端初始化的代码示例:
using Minio;
using Minio.DataModel;
using System;
using System.Threading.Tasks;
public class MinioUploadHelper
{
private readonly IMinioClient _minioClient;
private readonly string _bucketName;
/// <summary>
/// 初始化MinIO客户端
/// </summary>
/// <param name="endpoint">MinIO服务端点,如127.0.0.1:9000</param>
/// <param name="accessKey">访问密钥</param>
/// <param name="secretKey">秘密密钥</param>
/// <param name="bucketName">目标存储桶名称</param>
public MinioUploadHelper(string endpoint, string accessKey, string secretKey, string bucketName)
{
_minioClient = new MinioClient()
.WithEndpoint(endpoint)
.WithCredentials(accessKey, secretKey)
.WithSSL(false) // 如果是HTTPS则设为true
.Build();
_bucketName = bucketName;
}
}
存储桶检查与创建
上传文件前需要确保目标存储桶已经存在,如果不存在则自动创建,同时可以设置存储桶的访问策略,避免后续上传后出现权限问题。
/// <summary>
/// 检查并创建存储桶
/// </summary>
public async Task EnsureBucketExistsAsync()
{
bool bucketExists = await _minioClient.BucketExistsAsync(new BucketExistsArgs()
.WithBucket(_bucketName));
if (!bucketExists)
{
await _minioClient.MakeBucketAsync(new MakeBucketArgs()
.WithBucket(_bucketName));
Console.WriteLine($"存储桶{_bucketName}创建成功");
}
else
{
Console.WriteLine($"存储桶{_bucketName}已存在");
}
}
普通文件上传实现
对于小文件,可以直接使用简单的上传接口,指定本地文件路径、存储桶名称和上传后的对象名称即可完成上传。
/// <summary>
/// 上传单个普通文件
/// </summary>
/// <param name="localFilePath">本地文件完整路径</param>
/// <param name="objectName">上传后的对象名称,可包含路径前缀</param>
public async Task UploadSingleFileAsync(string localFilePath, string objectName)
{
await _minioClient.PutObjectAsync(new PutObjectArgs()
.WithBucket(_bucketName)
.WithObject(objectName)
.WithFileName(localFilePath));
Console.WriteLine($"文件{localFilePath}上传成功,对象名称为{objectName}");
}
大文件分片上传实现
当上传的文件体积较大时,普通上传容易出现超时或者失败的问题,此时可以使用MinIO的分片上传功能,将大文件拆分为多个分片并行上传,提升上传成功率。
/// <summary>
/// 大文件分片上传
/// </summary>
/// <param name="localFilePath">本地大文件完整路径</param>
/// <param name="objectName">上传后的对象名称</param>
/// <param name="partSize">每个分片大小,默认5MB</param>
public async Task UploadLargeFileAsync(string localFilePath, string objectName, long partSize = 5 * 1024 * 1024)
{
await _minioClient.PutObjectAsync(new PutObjectArgs()
.WithBucket(_bucketName)
.WithObject(objectName)
.WithFileName(localFilePath)
.WithPartSize(partSize));
Console.WriteLine($"大文件{localFilePath}分片上传成功");
}
上传进度监控
在实际业务中,往往需要展示文件上传的进度,MinIO SDK支持通过回调的方式获取上传进度,方便开发者实现进度条等交互效果。
/// <summary>
/// 带进度回调的文件上传
/// </summary>
/// <param name="localFilePath">本地文件路径</param>
/// <param name="objectName">对象名称</param>
/// <param name="progressCallback">进度回调,参数为上传百分比</param>
public async Task UploadWithProgressAsync(string localFilePath, string objectName, Action<double> progressCallback)
{
await _minioClient.PutObjectAsync(new PutObjectArgs()
.WithBucket(_bucketName)
.WithObject(objectName)
.WithFileName(localFilePath)
.WithProgressCallback((bytesTransferred, totalBytes) =>
{
double progress = (double)bytesTransferred / totalBytes * 100;
progressCallback?.Invoke(progress);
}));
}
常见问题与注意事项
- MinIO服务端点如果是HTTP协议,初始化客户端时需要设置WithSSL(false),否则会出现连接失败的问题。
- 对象名称可以包含斜杠分隔符,实现类似文件夹的层级结构,例如
images/2024/avatar.jpg。 - 分片上传的分片大小建议设置为5MB以上,过小的分片会增加请求次数,降低上传效率。
- 上传完成后可以通过GetObjectAsync接口验证文件是否上传成功,获取文件的元数据信息。
C#MinIOS3_protocol对象存储文件上传修改时间:2026-06-29 08:21:32