最近想配置一款可以存儲文件的服務(wù)器,如果使用阿里云OSS、七牛云、騰訊云需要收取比較高的費(fèi)用,為了節(jié)約成本,考慮使用免費(fèi)開源的軟件進(jìn)行部署,然后對fastDFS和MiniO進(jìn)行了對比:
一:安裝部署(運(yùn)維)復(fù)雜度
fastDFS分布式服務(wù)部署完成,需要具備以下的知識:
linux基礎(chǔ)的目錄操作
常用的分布式主從原理
C語言代碼的編譯
nginx安裝部署
nginx插件的使用(防盜鏈)
如果僅僅是上面的這些基礎(chǔ)知識,安排幾個(gè)程序員學(xué)一學(xué)還好說。主要是fastdfs的部署結(jié)構(gòu)之復(fù)雜,如果我長時(shí)間不回顧,自己都會忘了這復(fù)雜的架構(gòu)是怎么回事。
當(dāng)我看到MinIO的安裝過程之后,以及分布式的部署命令之后(分布式MinIO快速入門),放棄fastDFS的決心就已經(jīng)做出了一大半。
說白了:FastDFS的部署不過是零件的組裝過程,需要你去理解fastDFS的架構(gòu)設(shè)計(jì),才能夠正確的安裝部署。MinIO在安裝的過程是黑盒的,你不用去深入關(guān)注它的架構(gòu),也不需要你進(jìn)行零件組裝,基本上可以做到開箱即用。普通的技術(shù)人員就能夠參與后期運(yùn)維。
二:文檔
我覺得從我知道fastDFS開始,也有十年了。竟然沒有官方文檔,所有的文檔全是某某公司的自己總結(jié)的文檔,或者是某某網(wǎng)友自己總結(jié)的文檔。
從這點(diǎn)上看fastDFS真的是一敗涂地,當(dāng)然阿里余慶大神在做這個(gè)項(xiàng)目的時(shí)候可能也沒有考慮到后來會有這么多人用。即使用的人多了,在余慶大神眼里可能覺得這只是自己開發(fā)的一個(gè)小玩具,沒有繼續(xù)深入運(yùn)營的必要。
三:開源項(xiàng)目運(yùn)營組織
fastdfs是阿里余慶做的一個(gè)個(gè)人項(xiàng)目,在一些互聯(lián)網(wǎng)創(chuàng)業(yè)公司中有應(yīng)用,沒有官網(wǎng),不活躍,6個(gè)contributors。目前已經(jīng)很少做更新。
MinIO目前是由2014年在硅谷創(chuàng)立的公司MinIO.Inc運(yùn)營的開源項(xiàng)目,社區(qū)論壇的活躍度目前也非常的不錯(cuò)。
四:UI界面
我們都知道fastDFS默認(rèn)是不帶UI界面的,MinIO有比較豐富的UI界面
五:性能
MinIO號稱是世界上速度最快的對象存儲服務(wù)器。在標(biāo)準(zhǔn)硬件上,對象存儲的讀/寫速度最高可以達(dá)到183 GB/s和171 GB/s。關(guān)于fastDFS我曾經(jīng)單線程測試寫了20萬個(gè)文件,總共200G,大約用時(shí)10個(gè)小時(shí)??傮w上是很難達(dá)到MinIO“號稱的”以G為單位的每秒讀寫速度。
六:容器化支持
MinIO提供了與k8s、etcd、docker等容器化技術(shù)深度集成方案,可以說就是為了云環(huán)境而生的。這點(diǎn)是FastDFS不具備的。
七:豐富的SDK支持
fastDFS目前提供了 C 和 Java SDK ,以及 PHP 擴(kuò)展 SDK。下圖是MinIO提供的SDK支持,MinIO幾乎提供了所有主流開發(fā)語言的SDK以及文檔。同志們,重要的是文檔。
?八:AWS?S3標(biāo)準(zhǔn)兼容
Amazon的S3 API是對象存儲領(lǐng)域的事實(shí)標(biāo)準(zhǔn)。MinIO是S3兼容性的事實(shí)上的標(biāo)準(zhǔn),是第一個(gè)采用API和第一個(gè)添加對S3 Select支持的標(biāo)準(zhǔn)之一。包括微軟Azure在內(nèi)的750多家公司使用MinIO的S3網(wǎng)關(guān),這一數(shù)字超過了業(yè)內(nèi)其他公司的總和。
文檔地址:MinIO | The MinIO Quickstart Guide
安裝包下載地址:?https://dl.minio.io/server/minio/release/windows-amd64/minio.exe
一、安裝部署
1、下載安裝包(下載地址在上面)
2、放到磁盤中,后面會以這個(gè)文件進(jìn)行服務(wù)器安裝
3、磁盤新建一個(gè)目錄用于存放上傳文件,比如我創(chuàng)建的為:Data
?4、運(yùn)行控制臺程序:切換到安裝包所在目錄(后面部分為存儲路徑), 輸入命令:minio.exe server C:\minio\Data
?5、打開瀏覽器,訪問:http://127.0.0.1:9000 用戶名和密碼默認(rèn)為:minioadmin,主界面如下
??二、注冊成window服務(wù)
1. 下載winsw,下載地址:Releases · winsw/winsw · GitHub
CSDN下載地址:https://download.csdn.net/download/feritylamb/86394140
?
2. 將WinSW-net461.exe復(fù)制到自定義的目錄,并重命名為自己想命名的服務(wù)名稱minio-server.exe
?3.?同目錄下創(chuàng)建minio-server.xml。特別注意,xml和exe必須同名
?4.?配置minio-server.xml文件
5.新建run.bat文件,內(nèi)容如下:
set MINIO_ACCESS_KEY=admin
set MINIO_SECRET_KEY=12345678
minio.exe server C:\minio\Data
帶密碼帶自己定義端口9991啟動(dòng)命令:
set MINIO_ACCESS_KEY=admin
set MINIO_SECRET_KEY=12345678
minio.exe server --address:9991 C:\minio\Data
?5.?使用minio-server.exe install安裝服務(wù)
安裝服務(wù)命令:minio-server.exe install
啟動(dòng)服務(wù)命令:minio-server.exe start
停止服務(wù)命令:minio-server.exe stop
移除服務(wù)命令:sc delete minio-server
xml配置文件如下:
<service>
<id>minio-server</id>
<name>minio-server</name>
<description>minio文件存儲服務(wù)器</description>
<!-- 可設(shè)置環(huán)境變量 -->
<env name="HOME" value="%BASE%"/>
<executable>%BASE%\minio.exe</executable>
<arguments>server "%BASE%\data"</arguments>
<!-- <logmode>rotate</logmode> -->
<logpath>%BASE%\logs</logpath>
<log mode="roll-by-size-time">
<sizeThreshold>10240</sizeThreshold>
<pattern>yyyyMMdd</pattern>
<autoRollAtTime>00:00:00</autoRollAtTime>
<zipOlderThanNumDays>5</zipOlderThanNumDays>
<zipDateFormat>yyyyMMdd</zipDateFormat>
</log>
</service>
?注:如果啟動(dòng)不成功,可以把以上description里面的中文去掉
?三、C#文件上傳下載文章來源:http://www.zghlxwxcb.cn/news/detail-786789.html
public async void testupload()
{
try
{
MinioClient minio = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
//桶名稱
string buckName = "202110001";
//判斷桶是否存在,如果不存在則創(chuàng)建桶,否則上傳文件會異常
var exists = await MinioHelper.BucketExists(minio, buckName);
if (!exists)
{
//創(chuàng)建桶
await MinioHelper.MakeBucket(minio, buckName);
}
//上傳文件(桶下面可以自定義文件夾。如:1027/20211027001.jpg 則會創(chuàng)建一個(gè)1027文件夾)
var result = await MinioHelper.FPutObject(minio, buckName, "1027/20211027001.png", "E:\\202110271417.png");
//下載文件地址:192.168.90.128:9000+桶名稱+文件名稱
}
catch (Exception ex)
{
string str = ex.Message;
}
}
?四、minio文件操作幫助類文章來源地址http://www.zghlxwxcb.cn/news/detail-786789.html
public class MinioHelper
{
#region 操作存儲桶
/// <summary>創(chuàng)建存儲桶
/// 創(chuàng)建存儲桶
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="loc">可選參數(shù)</param>
/// <returns></returns>
public async static Task<bool> MakeBucket(MinioClient minio, string bucketName, string loc = "us-east-1")
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
throw new Exception(string.Format("存儲桶[{0}]已存在", bucketName));
}
else
{
await minio.MakeBucketAsync(bucketName, loc);
flag = true;
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>列出所有的存儲桶
/// 列出所有的存儲桶
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <returns></returns>
public async static Task<Tuple<bool, Minio.DataModel.ListAllMyBucketsResult>> ListBuckets(MinioClient minio)
{
bool flag = false;
var list = new Minio.DataModel.ListAllMyBucketsResult();
try
{
list = await minio.ListBucketsAsync();
flag = true;
//foreach (var bucket in list.Buckets)
//{
// Console.WriteLine($"{bucket.Name} {bucket.CreationDateDateTime}");
//}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, list);
}
/// <summary>檢查存儲桶是否存在
/// 檢查存儲桶是否存在
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
public async static Task<bool> BucketExists(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
flag = await minio.BucketExistsAsync(bucketName);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>刪除一個(gè)存儲桶
/// 刪除一個(gè)存儲桶
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
public async static Task<bool> RemoveBucket(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.RemoveBucketAsync(bucketName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>列出存儲桶里的對象
/// 列出存儲桶里的對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="prefix">對象的前綴</param>
/// <param name="recursive">true代表遞歸查找,false代表類似文件夾查找,以'/'分隔,不查子文件夾</param>
public static Tuple<bool, IObservable<Item>> ListObjects(MinioClient minio, string bucketName, string prefix = null, bool recursive = true)
{
bool flag = false;
IObservable<Item> observable = null;
try
{
var found = minio.BucketExistsAsync(bucketName);
if (found.Result)
{
observable = minio.ListObjectsAsync(bucketName, prefix, recursive);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
//IDisposable subscription = observable.Subscribe(
// item => Console.WriteLine($"Object: {item.Key}"),
// ex => Console.WriteLine($"OnError: {ex}"),
// () => Console.WriteLine($"Listed all objects in bucket {bucketName}\n"));
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, observable);
}
/// <summary>列出存儲桶中未完整上傳的對象
/// 列出存儲桶中未完整上傳的對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="prefix">對象的前綴</param>
/// <param name="recursive">true代表遞歸查找,false代表類似文件夾查找,以'/'分隔,不查子文件夾</param>
/// <returns></returns>
public static Tuple<bool, IObservable<Upload>> ListIncompleteUploads(MinioClient minio, string bucketName, string prefix = null, bool recursive = true)
{
bool flag = false;
IObservable<Upload> observable = null;
try
{
var found = minio.BucketExistsAsync(bucketName);
if (found.Result)
{
observable = minio.ListIncompleteUploads(bucketName, prefix, recursive);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
//IDisposable subscription = observable.Subscribe(
// item => Console.WriteLine($"OnNext: {item.Key}"),
// ex => Console.WriteLine($"OnError: {ex.Message}"),
// () => Console.WriteLine($"Listed the pending uploads to bucket {bucketName}"));
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, observable);
}
#endregion
#region 存儲桶策略
/// <summary>
/// 獲取存儲桶或者對象前綴的訪問權(quán)限
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
public async static Task<Tuple<bool, string>> GetPolicy(MinioClient minio, string bucketName)
{
bool flag = false;
string policyJson = string.Empty;
try
{
var found = minio.BucketExistsAsync(bucketName);
if (found.Result)
{
policyJson = await minio.GetPolicyAsync(bucketName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, policyJson);
}
/// <summary>
/// 針對存儲桶和對象前綴設(shè)置訪問策略
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
public async static Task<bool> SetPolicy(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
string policyJson = $@"{{""Version"":""2012-10-17"",""Statement"":[{{""Action"":[""s3:GetBucketLocation""],""Effect"":""Allow"",""Principal"":{{""AWS"":[""*""]}},""Resource"":[""arn:aws:s3:::{bucketName}""],""Sid"":""""}},{{""Action"":[""s3:ListBucket""],""Condition"":{{""StringEquals"":{{""s3:prefix"":[""foo"",""prefix/""]}}}},""Effect"":""Allow"",""Principal"":{{""AWS"":[""*""]}},""Resource"":[""arn:aws:s3:::{bucketName}""],""Sid"":""""}},{{""Action"":[""s3:GetObject""],""Effect"":""Allow"",""Principal"":{{""AWS"":[""*""]}},""Resource"":[""arn:aws:s3:::{bucketName}/foo*"",""arn:aws:s3:::{bucketName}/prefix/*""],""Sid"":""""}}]}}";
await minio.SetPolicyAsync(bucketName, policyJson);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
#endregion
#region 存儲桶通知
/// <summary>
/// 獲取存儲桶的通知配置
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
private async static Task<Tuple<bool, string>> GetBucketNotification(MinioClient minio, string bucketName)
{
bool flag = false;
string Ret = string.Empty;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
BucketNotification notifications = await minio.GetBucketNotificationsAsync(bucketName);
Ret = notifications.ToXML();
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, Ret);
}
/// <summary>
/// 給存儲桶設(shè)置通知
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
private async static Task<bool> SetBucketNotification(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
BucketNotification notification = new BucketNotification();
Arn topicArn = new Arn("aws", "sns", "us-west-1", "412334153608", "topicminio");
TopicConfig topicConfiguration = new TopicConfig(topicArn);
List<EventType> events = new List<EventType>() { EventType.ObjectCreatedPut, EventType.ObjectCreatedCopy };
topicConfiguration.AddEvents(events);
topicConfiguration.AddFilterPrefix("images");
topicConfiguration.AddFilterSuffix("jpg");
notification.AddTopic(topicConfiguration);
QueueConfig queueConfiguration = new QueueConfig("arn:aws:sqs:us-west-1:482314153608:testminioqueue1");
queueConfiguration.AddEvents(new List<EventType>() { EventType.ObjectCreatedCompleteMultipartUpload });
notification.AddQueue(queueConfiguration);
await minio.SetBucketNotificationsAsync(bucketName, notification);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>
/// 刪除存儲桶上所有配置的通知
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <returns></returns>
private async static Task<bool> RemoveAllBucketNotifications(MinioClient minio, string bucketName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.RemoveAllBucketNotificationsAsync(bucketName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
#endregion
#region 操作文件對象
/// <summary>
/// 從桶下載文件到本地
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="fileName">本地路徑</param>
/// <param name="sse"></param>
/// <returns></returns>
public async static Task<bool> FGetObject(MinioClient minio, string bucketName, string objectName, string fileName, ServerSideEncryption sse = null)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
await minio.GetObjectAsync(bucketName, objectName, fileName, sse).ConfigureAwait(false);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>
/// 上傳本地文件至存儲桶
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="fileName">本地路徑</param>
/// <returns></returns>
public async static Task<bool> FPutObject(MinioClient minio, string bucketName, string objectName, string fileName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.PutObjectAsync(bucketName, objectName, fileName, contentType: "application/octet-stream");
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
#endregion
#region Presigned操作
/// <summary>生成一個(gè)給HTTP GET請求用的presigned URL。瀏覽器/移動(dòng)端的客戶端可以用這個(gè)URL進(jìn)行下載,即使其所在的存儲桶是私有的。這個(gè)presigned URL可以設(shè)置一個(gè)失效時(shí)間,默認(rèn)值是7天。
/// 生成一個(gè)給HTTP GET請求用的presigned URL。瀏覽器/移動(dòng)端的客戶端可以用這個(gè)URL進(jìn)行下載,即使其所在的存儲桶是私有的。這個(gè)presigned URL可以設(shè)置一個(gè)失效時(shí)間,默認(rèn)值是7天。
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="expiresInt">失效時(shí)間(以秒為單位),默認(rèn)是7天,不得大于七天</param>
/// <param name="reqParams">額外的響應(yīng)頭信息,支持response-expires、response-content-type、response-cache-control、response-content-disposition</param>
/// <returns></returns>
public async static Task<Tuple<bool, string>> PresignedGetObject(MinioClient minio, string bucketName, string objectName, int expiresInt = 1000)
{
bool flag = false;
string Ret = string.Empty;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
var reqParams = new Dictionary<string, string> { { "response-content-type", "application/json" } };
string presignedUrl = await minio.PresignedGetObjectAsync(bucketName, objectName, expiresInt, reqParams);
Ret = presignedUrl;
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, Ret);
}
/// <summary>生成一個(gè)給HTTP PUT請求用的presigned URL。瀏覽器/移動(dòng)端的客戶端可以用這個(gè)URL進(jìn)行上傳,即使其所在的存儲桶是私有的。這個(gè)presigned URL可以設(shè)置一個(gè)失效時(shí)間,默認(rèn)值是7天。
/// 生成一個(gè)給HTTP PUT請求用的presigned URL。瀏覽器/移動(dòng)端的客戶端可以用這個(gè)URL進(jìn)行上傳,即使其所在的存儲桶是私有的。這個(gè)presigned URL可以設(shè)置一個(gè)失效時(shí)間,默認(rèn)值是7天。
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="expiresInt">失效時(shí)間(以秒為單位),默認(rèn)是7天,不得大于七天</param>
/// <returns></returns>
public async static Task<Tuple<bool, string>> PresignedPutObject(MinioClient minio, string bucketName, string objectName, int expiresInt = 1000)
{
bool flag = false;
string Ret = string.Empty;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
string presignedUrl = await minio.PresignedPutObjectAsync(bucketName, objectName, expiresInt);
Ret = presignedUrl;
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, Ret);
}
/// <summary>允許給POST請求的presigned URL設(shè)置策略,比如接收對象上傳的存儲桶名稱的策略,key名稱前綴,過期策略。
/// 允許給POST請求的presigned URL設(shè)置策略,比如接收對象上傳的存儲桶名稱的策略,key名稱前綴,過期策略。
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="PostPolicy">對象的post策略</param>
/// <returns></returns>
public async static Task<Tuple<bool, string, Dictionary<string, string>>> PresignedPostPolicy(MinioClient minio)
{
bool flag = false;
Tuple<string, Dictionary<string, string>> tdic = null;
try
{
PostPolicy form = new PostPolicy();
DateTime expiration = DateTime.UtcNow;
form.SetExpires(expiration.AddDays(10));
form.SetKey("my-objectname");
form.SetBucket("my-bucketname");
Tuple<string, Dictionary<string, string>> tuple = await minio.PresignedPostPolicyAsync(form);
tdic = tuple;
flag = true;
//string curlCommand = "curl -X POST ";
//foreach (KeyValuePair<string, string> pair in tuple.Item2)
//{
// curlCommand = curlCommand + $" -F {pair.Key}={pair.Value}";
//}
//curlCommand = curlCommand + " -F file=@/etc/bashrc " + tuple.Item1; // https://s3.amazonaws.com/my-bucketname";
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return Tuple.Create(flag, tdic.Item1, tdic.Item2);
}
#endregion
#region 操作對象
/// <summary>返回對象數(shù)據(jù)的流
/// 返回對象數(shù)據(jù)的流
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="callback">處理流的回調(diào)函數(shù)</param>
/// <returns></returns>
public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, Action<Stream> callback)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.StatObjectAsync(bucketName, objectName);
await minio.GetObjectAsync(bucketName, objectName, callback);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>下載對象指定區(qū)域的字節(jié)數(shù)組做為流。offset和length都必須傳
/// 下載對象指定區(qū)域的字節(jié)數(shù)組做為流。offset和length都必須傳
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="offset">offset 是起始字節(jié)的位置</param>
/// <param name="length">length是要讀取的長度</param>
/// <param name="callback">處理流的回調(diào)函數(shù)</param>
/// <returns></returns>
public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, long offset, long length, Action<Stream> callback)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.StatObjectAsync(bucketName, objectName);
await minio.GetObjectAsync(bucketName, objectName, offset, length, callback);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>下載并將文件保存到本地文件系統(tǒng)
/// 下載并將文件保存到本地文件系統(tǒng)
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="fileName">本地文件路徑</param>
/// <returns></returns>
public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, string fileName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
await minio.StatObjectAsync(bucketName, objectName);
await minio.GetObjectAsync(bucketName, objectName, fileName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>通過文件上傳到對象中
/// 通過文件上傳到對象中
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="filePath">要上傳的本地文件名</param>
/// <param name="contentType">文件的Content type,默認(rèn)是"application/octet-stream"</param>
/// <param name="metaData">元數(shù)據(jù)頭信息的Dictionary對象,默認(rèn)是null</param>
/// <returns></returns>
public async static Task<bool> PutObjectAsync(MinioClient minio, string bucketName, string objectName, string filePath, string contentType = "application/octet-stream", Dictionary<string, string> metaData = null)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.PutObjectAsync(bucketName, objectName, filePath, contentType, metaData);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>通過Stream上傳對象
/// 通過Stream上傳對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <param name="data">要上傳的Stream對象</param>
/// <param name="size">流的大小</param>
/// <param name="contentType">文件的Content type,默認(rèn)是"application/octet-stream"</param>
/// <param name="metaData">元數(shù)據(jù)頭信息的Dictionary對象,默認(rèn)是null</param>
/// <returns></returns>
public async static Task<bool> PutObjectAsync(MinioClient minio, string bucketName, string objectName, Stream data, long size, string contentType = "application/octet-stream", Dictionary<string, string> metaData = null)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
//byte[] bs = File.ReadAllBytes(fileName);
//System.IO.MemoryStream filestream = new System.IO.MemoryStream(bs);
await minio.PutObjectAsync(bucketName, objectName, data, size, contentType, metaData);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>獲取對象的元數(shù)據(jù)
/// 獲取對象的元數(shù)據(jù)
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <returns></returns>
public async static Task<bool> StatObject(MinioClient minio, string bucketName, string bucketObject)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
ObjectStat statObject = await minio.StatObjectAsync(bucketName, bucketObject);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>從objectName指定的對象中將數(shù)據(jù)拷貝到destObjectName指定的對象
/// 從objectName指定的對象中將數(shù)據(jù)拷貝到destObjectName指定的對象
/// </summary>
/// <param name="minio"></param>
/// <param name="fromBucketName">源存儲桶名稱</param>
/// <param name="fromObjectName">源存儲桶中的源對象名稱</param>
/// <param name="destBucketName">目標(biāo)存儲桶名稱</param>
/// <param name="destObjectName">要?jiǎng)?chuàng)建的目標(biāo)對象名稱,如果為空,默認(rèn)為源對象名稱</param>
/// <param name="copyConditions">拷貝操作的一些條件Map</param>
/// <param name="sseSrc"></param>
/// <param name="sseDest"></param>
/// <returns></returns>
public async static Task<bool> CopyObject(MinioClient minio, string fromBucketName, string fromObjectName, string destBucketName, string destObjectName, CopyConditions copyConditions = null, ServerSideEncryption sseSrc = null, ServerSideEncryption sseDest = null)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(fromBucketName);
if (!found)
{
throw new Exception(string.Format("源存儲桶[{0}]不存在", fromBucketName));
}
bool foundtwo = await minio.BucketExistsAsync(destBucketName);
if (!foundtwo)
{
throw new Exception(string.Format("目標(biāo)存儲桶[{0}]不存在", destBucketName));
}
await minio.CopyObjectAsync(fromBucketName, fromObjectName, destBucketName, destObjectName, copyConditions, null, sseSrc, sseDest);
flag = true;
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>刪除一個(gè)對象
/// 刪除一個(gè)對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <returns></returns>
public async static Task<bool> RemoveObject(MinioClient minio, string bucketName, string objectName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.RemoveObjectAsync(bucketName, objectName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>刪除多個(gè)對象
/// 刪除多個(gè)對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectsList">含有多個(gè)對象名稱的IEnumerable</param>
/// <returns></returns>
public static async Task<bool> RemoveObjects(MinioClient minio, string bucketName, List<string> objectsList)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
if (objectsList != null)
{
IObservable<DeleteError> objectsOservable = await minio.RemoveObjectAsync(bucketName, objectsList).ConfigureAwait(false);
flag = true;
//IDisposable objectsSubscription = objectsOservable.Subscribe(
// objDeleteError => Console.WriteLine($"Object: {objDeleteError.Key}"),
// ex => Console.WriteLine($"OnError: {ex}"),
// () =>
// {
// Console.WriteLine($"Removed objects in list from {bucketName}\n");
// });
//return;
}
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
/// <summary>刪除一個(gè)未完整上傳的對象
/// 刪除一個(gè)未完整上傳的對象
/// </summary>
/// <param name="minio">連接實(shí)例</param>
/// <param name="bucketName">存儲桶名稱</param>
/// <param name="objectName">存儲桶里的對象名稱</param>
/// <returns></returns>
public async static Task<bool> RemoveIncompleteUpload(MinioClient minio, string bucketName, string objectName)
{
bool flag = false;
try
{
bool found = await minio.BucketExistsAsync(bucketName);
if (found)
{
await minio.RemoveIncompleteUploadAsync(bucketName, objectName);
flag = true;
}
else
{
throw new Exception(string.Format("存儲桶[{0}]不存在", bucketName));
}
}
catch (MinioException e)
{
throw new Exception(e.Message);
}
return flag;
}
#endregion
}
到了這里,關(guān)于windows系統(tǒng)部署minio,以及添加到系統(tǒng)服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!