一、准备工作
1、本地部署MinIO服务
需要在本地部署MinIO,并启动服务;可以参考这篇文章
Windows部署MinIO,搭建本地对象存储服务-CSDN博客
2、创建MinIO的Access Key
在MinIO控制台,选择【Access Keys】,点击【Create access key】;
点击【Create】创建用于连接MinIO服务的Key和Secret(很重要,一定要另存下来);
3、创建.net 项目
打开Visual Studio,新建项目,选择Web Api框架
选择.net8.0
4、下载MinIO sdk
使用NuGet包管理器找到并安装MinIIO的sdk,如下图所示,
这里安装的是最新版6.0.2;
5、相关文档
以官网的英文文档为主,中文文档为辅;
二、编写MinIO工具类
在代码中编写一个用来连接MinIO服务的工具类【MinIO.cs】,放在项目的【Helper】文件夹中;
【Helper/MinIO.cs】
using Minio;
namespace Zyl_MinIO_Demo.Helper
{
public class MinIO
{
private static string endPoint = "127.0.0.1:9001";
private static string accessKey = "连接minio服务的key";
private static string secretKey= "连接minio服务的secret";
private static bool secure = false;
public static MinioClient CreateMinioClient()
{
MinioClient minioClient = (MinioClient)new MinioClient()
.WithEndpoint(endpoint)
.WithCredentials(accessKey, secretKey)
.WithSSL(secure)
.Build();
return minioClient;
}
}
}
// 该方法用来初始化MinIO对象。
MinioClient minioClient = new MinioClient()
.WithEndpoint(endPoint)
.WithCredentials(accessKey, secretKey)
.WithSSL(secure)
.Build();
- endPoint :MinIO服务启动的URL,注意自己启动服务的端口号;
- accessKey :在MinIO控制台申请的Access Key;
- secretKey:在MinIO控制台申请的Access Secret;
- secure :布尔值(默认值 true),是否启用HTTPS;
三、管理存储桶
1、MyBucket类
在【Managers】文件夹中新建【MyBucket】类,用来管理存储桶;
【Managers/MyBucket.cs】
using Minio.DataModel.Args;
using Minio.Exceptions;
using Minio;
using Zyl_MinIO_Demo.Helper;
using Minio.DataModel.Result;
namespace Zyl_MinIO_Demo.Managers
{
public class MyBucket
{
// 实例化 minioClient
private static MinioClient minioClient = MinIO.CreateMinioClient();
/// <summary>
/// 1、判断bucket是否存在
/// </summary>
/// <param name="bucketName"></param>
/// <returns></returns>
public static async Task<string> IsExistStr(string bucketName){
try
{
BucketExistsArgs args = new BucketExistsArgs().WithBucket(bucketName);
bool found = await minioClient.BucketExistsAsync(args).ConfigureAwait(false);
Console.WriteLine("found。。。。。。", found);
if (found)
{
Console.WriteLine($"{bucketName}桶已存在");
return $"{bucketName}桶已存在";
}
else
{
Console.WriteLine($"{bucketName}桶不存在");
return $"{bucketName}桶不存在";
}
}
catch (MinioException e)
{
Console.WriteLine("[Bucket] Exception: {0}", e);
return "出错啦!!!";
}
}
/// <summary>
/// 2、创建一个bucket
/// </summary>
/// <param name="bucketName"></param>
/// <returns></returns>
public static async Task<string> Create(string? bucketName)
{
try
{
BucketExistsArgs args = new BucketExistsArgs().WithBucket(bucketName);
bool found = await minioClient.BucketExistsAsync(args).ConfigureAwait(false);
if (found)
{
return $"{bucketName}桶已存在";
}
else
{
MakeBucketArgs makeBucketArgs = new MakeBucketArgs().WithBucket(bucketName);
await minioClient.MakeBucketAsync(makeBucketArgs).ConfigureAwait(false);
return $"{bucketName}桶已成功创建";
}
}
catch (MinioException e)
{
Console.WriteLine("[Bucket] Exception: {0}", e);
return "出错啦!!!";
}
}
/// <summary>
/// 3、移除一个bucket
/// </summary>
/// <param name="bucketName"></param>
/// <returns></returns>
public static async Task<string> Delete(string? bucketName)
{
try
{
BucketExistsArgs args = new BucketExistsArgs().WithBucket(bucketName);
bool found = await minioClient.BucketExistsAsync(args).ConfigureAwait(false);
if (!found)
{
return $"{bucketName}桶不存在";
}
else
{
RemoveBucketArgs removeBucketArgs = new RemoveBucketArgs().WithBucket(bucketName);
await minioClient.RemoveBucketAsync(removeBucketArgs);
return $"{bucketName}桶删除成功";
}
}
catch (MinioException e)
{
Console.WriteLine("[Bucket] Exception: {0}", e);
return "出错啦!!!";
}
}
/// <summary>
/// 4、获取已有的bucket列表
/// </summary>
/// <returns></returns>
public static async Task<ListAllMyBucketsResult?> GetList()
{
try
{
return await minioClient.ListBucketsAsync();
}
catch (MinioException e)
{
Console.WriteLine("Error occurred: " + e);
return null ;
}
}
}
}
(1)判断bucket是否存在
Task<bool> BucketExistsAsync(BucketExistsArgs args)
- 判断一个指定名称的存储桶是否存在
- 返回一个布尔值true(存在),或false(不存在);
(2)新建bucket
Task MakeBucketAsync(MakeBucketArgs args)
- 创建一个指定名称的存储桶;
- 创建失败,则返回异常信息;
(3)删除bucket
Task RemoveBucketAsync(RemoveBucketArgs args)
- 移除一个指定名称的存储桶;
- 任务返回移除失败时的异常信息;
- 当桶中有内容时,则不会被删除;
(4)获取bucket列表
Task<ListAllMyBucketsResult> ListBucketsAsync()
- 用来获取buckets列表数据;
2、BucketController
在Controllers文件夹下,新建一个空的API控制器,用来给前端人员暴露接口;
【Controllers/BucketController.cs】
using Microsoft.AspNetCore.Mvc;
using Minio;
using Minio.DataModel.Result;
using Zyl_MinIO_Demo.Managers;
namespace Zyl_MinIO_Demo.Controllers
{
/// <summary>
/// 管理 MinIO 中的 Bucket
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class BucketController : ControllerBase
{
/// <summary>
/// 1、判断指定bucket是否存在
/// </summary>
/// <param name="bucketName">bucket 名称</param>
/// <returns></returns>
[HttpPost]
public async Task<string> IsBucketExit(string bucketName)
{
return await MyBucket.IsExist(bucketName) ? $"{bucketName}桶已存在" : $"{bucketName}桶不存在";
}
/// <summary>
/// 2、 创建bucket
/// </summary>
/// <param name="bucketName">bucket 名称</param>
/// <returns></returns>
[HttpPost]
public async Task<string> CreateBucket(string bucketName)
{
return await MyBucket.Create(bucketName);
}
/// <summary>
/// 3、移除bucket
/// </summary>
/// <param name="bucketName">bucket 名称</param>
/// <returns></returns>
[HttpDelete]
public async Task<string> DeleteBucket(string bucketName)
{
return await MyBucket.Delete(bucketName);
}
/// <summary>
/// 4、获取bucket列表
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<ListAllMyBucketsResult?> GetBucketList()
{
return await MyBucket.GetList();
}
}
}
3、实现效果
启动项目,使用Swagger进行接口测试;
注意:
- 需要确保,项目中已经配置了Swagger;
- 需要确保,MinIO服务已经启动;
项目启动后的swagger页面:
可参考上方链接配置swagger;
先在MinIO控制台中创建一个名为zyl的bucket;
(1)判断bucket是否存在
输入桶名,点击测试;
执行后可以看到数据正常返回;
(2)新建bucket
(3)删除bucket
(4)获取bucket列表
四、管理文件
1、MyObject类
在【Managers】文件夹中新建【MyObject】类,用来管理存储桶中的文件对象;
【Managers/MyObject.cs】
using Minio.DataModel.Args;
using Minio;
using Zyl_MinIO_Demo.Helper;
using Minio.Exceptions;
namespace Zyl_MinIO_Demo.Managers
{
public class MyObject
{
private static readonly MinioClient minioClient = MinIO.CreateMinioClient();
/// <summary>
/// 1、下载文件 到本地
/// </summary>
public async static Task<String> DownloadFile(string bucketName, string objectName) {
try
{
string folderPath = "D:\\minio-download-files\\";
if (!Directory.Exists(folderPath)) {
DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
directoryInfo.Create();
}
StatObjectArgs statObjectArgs = new StatObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName);
await minioClient.StatObjectAsync(statObjectArgs);
GetObjectArgs getObjectArgs = new GetObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithFile(folderPath + objectName);
await minioClient.GetObjectAsync(getObjectArgs);
return "Success";
}
catch (MinioException e)
{
return $"Failure\r\n{e.Message}";
}
}
/// <summary>
/// 2、上传文件 指定文件
/// </summary>
public async static Task<string> UploadFile(string bucketName,string fileFullPath)
{
try
{
// 判断bucket是否存在
bool isExit = await MyBucket.IsExist(bucketName);
if (!isExit)
{
Console.Out.WriteLine($"{bucketName}桶不存在");
return $"{bucketName}桶不存在,文件上传失败";
}
string objectName = fileFullPath.Split("\\")[^1];
// 上传文件
PutObjectArgs putObjectArgs = new PutObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithFileName(fileFullPath)
.WithContentType("application/octet-stream");
await minioClient.PutObjectAsync(putObjectArgs).ConfigureAwait(false);
return $"{objectName}上传成功";
}
catch (Exception e)
{
return $"Failure\r\n{e.Message}";
}
}
/// <summary>
/// 3、删除 指定文件
/// </summary>
public async static Task<string> DeleteFile(string bucketName, string objectName)
{
try
{
// 判断bucket是否存在
bool isExit = await MyBucket.IsExist(bucketName);
if (!isExit)
{
return $"{bucketName}桶不存在,文件删除失败";
}
RemoveObjectArgs removeObjectArgs = new RemoveObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName);
await minioClient.RemoveObjectAsync(removeObjectArgs);
return $"{bucketName}桶中的{objectName}文件删除成功";
}
catch (MinioException e)
{
return $"Failure\r\n{e.Message}";
}
}
/// <summary>
/// 4、获取指定文件的url链接
/// </summary>
public async static Task<String> GetFileUrl(string bucketName, string objectName)
{
try
{
PresignedGetObjectArgs args = new PresignedGetObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithExpiry(60 * 60 * 24 * 7);
return await minioClient.PresignedGetObjectAsync(args);
}
catch (MinioException e)
{
return $"Failure\r\n{e.Message}";
}
}
}
}
(1)下载文件对象
Task GetObjectAsync(GetObjectArgs args)
- 用来下载一个文件对象,并保存到本地;
(2)上传文件对象
Task PutObjectAsync(PutObjectArgs args)
- 若上传的文件名于之前相同,则会覆盖;
(3)删除文件对象
Task RemoveObjectAsync(RemoveObjectArgs args)
(4)获取文件对象URL
Task<string> PresignedGetObjectAsync(PresignedGetObjectArgs args)
- 返回的URL可用来直接下载该文件对象;
- 返回的URL有效期为7天(默认),也可以自行设置(秒数);
2、ObjectController
【Controllers/ObjectController.cs】
using Microsoft.AspNetCore.Mvc;
using Zyl_MinIO_Demo.Managers;
namespace Zyl_MinIO_Demo.Controllers
{
/// <summary>
/// 管理 MinIO对象(默认zyl bucket桶)
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class ObjectController : ControllerBase
{
/// <summary>
/// 1、下载 bucket中的文件
/// </summary>
/// <remarks>
/// 会保存在 D:\\minio-download-files 文件夹内;
/// 若本地D盘中没有该文件夹,则会自动创建;
/// </remarks>
/// <param name="objectName">文件名</param>
/// <param name="bucketName">桶名,默认zyl</param>
[HttpPost]
public async Task<string> DownloadObject( string objectName, string bucketName = "zyl")
{
return await MyObject.DownloadFile(bucketName, objectName);
}
///<summary>
/// 2、上传 本地指定文件
/// </summary>
/// <remarks>
/// 上传同名文件,会覆盖之前的
/// </remarks>
/// <param name="fileFullPath">上传文件的完整绝对路径,例如:D:\test\test.txt</param>
/// <param name="bucketName">桶名,默认zyl</param>
[HttpPost]
public async Task<string> UploadObject(string fileFullPath, string bucketName = "zyl")
{
return await MyObject.UploadFile(bucketName, fileFullPath);
}
/// <summary>
/// 3、删除 指定桶中的指定文件
/// </summary>
/// <param name="objectName">文件名</param>
/// <param name="bucketName">桶名,默认zyl</param>
[HttpDelete]
public async Task<string> DeleteObject(string objectName, string bucketName = "zyl")
{
return await MyObject.DeleteFile(bucketName, objectName);
}
/// <summary>
/// 4、获取 指定文件的Url链接 (有效期 7天)
/// </summary>
/// <remarks>
/// 只能是已经存在于minio中的任意文件
/// </remarks>
/// <param name="objectName">文件名</param>
/// <param name="bucketName">桶名,默认zyl</param>
/// <returns></returns>
[HttpPost]
public async Task<string> GetObjectUrl(string objectName, string bucketName = "zyl") {
return await MyObject.GetFileUrl(bucketName, objectName);
}
}
}
3、实现效果
在Swagger页面,可以看到我们新增的文件对象相关接口;
(1)下载指定文件
- 这里的默认bucket,确保在使用之前已经创建;
- 文件会下载到本地D盘的【minio-downlo-files】文件夹中,没有该文件夹会自动创建;
(2)上传指定文件
- 第一个参数应该填写待上传文件的完整绝对路径,这里上传的是D盘下test文件夹中的text.txt文件;
- 上传到minio服务中的文件名取自待上传的文件名,若与之前的文件名相同,会进行覆盖;
(3)删除指定文件
(4)获取指定文件URL
- 需要确保minio中已经上传了该文件;
- 将返回的URL链接放在浏览器的地址栏,按回车即可下载查看;
======================================================================
每天进步一点点,记录一下MinIO的学习笔记;
刚开始接触后端,代码略显生涩,嘻嘻嘻;
还望走过路过的各位大佬多多指点~