• windows系统部署minio,以及添加到系统服务器


    最近想配置一款可以存储文件的服务器,如果使用阿里云OSS、七牛云、腾讯云需要收取比较高的费用,为了节约成本,考虑使用免费开源的软件进行部署,然后对fastDFS和MiniO进行了对比:

    一:安装部署(运维)复杂度

    fastDFS分布式服务部署完成,需要具备以下的知识:

    linux基础的目录操作
    常用的分布式主从原理
    C语言代码的编译
    nginx安装部署
    nginx插件的使用(防盗链)

    如果仅仅是上面的这些基础知识,安排几个程序员学一学还好说。主要是fastdfs的部署结构之复杂,如果我长时间不回顾,自己都会忘了这复杂的架构是怎么回事。

    当我看到MinIO的安装过程之后,以及分布式的部署命令之后(分布式MinIO快速入门),放弃fastDFS的决心就已经做出了一大半。

    说白了:FastDFS的部署不过是零件的组装过程,需要你去理解fastDFS的架构设计,才能够正确的安装部署。MinIO在安装的过程是黑盒的,你不用去深入关注它的架构,也不需要你进行零件组装,基本上可以做到开箱即用。普通的技术人员就能够参与后期运维。

    二:文档

    我觉得从我知道fastDFS开始,也有十年了。竟然没有官方文档,所有的文档全是某某公司的自己总结的文档,或者是某某网友自己总结的文档。

    从这点上看fastDFS真的是一败涂地,当然阿里余庆大神在做这个项目的时候可能也没有考虑到后来会有这么多人用。即使用的人多了,在余庆大神眼里可能觉得这只是自己开发的一个小玩具,没有继续深入运营的必要。

    三:开源项目运营组织

    fastdfs是阿里余庆做的一个个人项目,在一些互联网创业公司中有应用,没有官网,不活跃,6个contributors。目前已经很少做更新。

    MinIO目前是由2014年在硅谷创立的公司MinIO.Inc运营的开源项目,社区论坛的活跃度目前也非常的不错。

    四:UI界面


    我们都知道fastDFS默认是不带UI界面的,MinIO有比较丰富的UI界面

    五:性能

    MinIO号称是世界上速度最快的对象存储服务器。在标准硬件上,对象存储的读/写速度最高可以达到183 GB/s和171 GB/s。关于fastDFS我曾经单线程测试写了20万个文件,总共200G,大约用时10个小时。总体上是很难达到MinIO“号称的”以G为单位的每秒读写速度。

    六:容器化支持

    MinIO提供了与k8s、etcd、docker等容器化技术深度集成方案,可以说就是为了云环境而生的。这点是FastDFS不具备的。

    七:丰富的SDK支持

    fastDFS目前提供了 C 和 Java SDK ,以及 PHP 扩展 SDK。下图是MinIO提供的SDK支持,MinIO几乎提供了所有主流开发语言的SDK以及文档。同志们,重要的是文档。

     八:AWS S3标准兼容

    Amazon的S3 API是对象存储领域的事实标准。MinIO是S3兼容性的事实上的标准,是第一个采用API和第一个添加对S3 Select支持的标准之一。包括微软Azure在内的750多家公司使用MinIO的S3网关,这一数字超过了业内其他公司的总和。

    文档地址:MinIO | The MinIO Quickstart Guide

    安装包下载地址: https://dl.minio.io/server/minio/release/windows-amd64/minio.exe

    一、安装部署

    1、下载安装包(下载地址在上面)

    2、放到磁盘中,后面会以这个文件进行服务器安装

    3、磁盘新建一个目录用于存放上传文件,比如我创建的为:Data

     4、运行控制台程序:切换到安装包所在目录(后面部分为存储路径), 输入命令:minio.exe server C:\minio\Data

     5、打开浏览器,访问:http://127.0.0.1:9000 用户名和密码默认为:minioadmin,主界面如下

      二、注册成window服务

    1. 下载winsw,下载地址:Releases · winsw/winsw · GitHub

    CSDN下载地址:https://download.csdn.net/download/feritylamb/86394140

     

    2. 将WinSW-net461.exe复制到自定义的目录,并重命名为自己想命名的服务名称minio-server.exe

     3. 同目录下创建minio-server.xml。特别注意,xml和exe必须同名

     4. 配置minio-server.xml文件

    5.新建run.bat文件,内容如下:

    1. set MINIO_ACCESS_KEY=admin
    2. set MINIO_SECRET_KEY=12345678
    3. minio.exe server C:\minio\Data
    4. 带密码带自己定义端口9991启动命令:
    5. set MINIO_ACCESS_KEY=admin
    6. set MINIO_SECRET_KEY=12345678
    7. minio.exe server --address:9991 C:\minio\Data

     5. 使用minio-server.exe install安装服务

    安装服务命令:minio-server.exe install

    启动服务命令:minio-server.exe start

    停止服务命令:minio-server.exe stop

    移除服务命令:sc delete minio-server

    xml配置文件如下:

    1. <service>
    2. <id>minio-serverid>
    3. <name>minio-servername>
    4. <description>minio文件存储服务器description>
    5. <env name="HOME" value="%BASE%"/>
    6. <executable>%BASE%\minio.exeexecutable>
    7. <arguments>server "%BASE%\data"arguments>
    8. <logpath>%BASE%\logslogpath>
    9. <log mode="roll-by-size-time">
    10. <sizeThreshold>10240sizeThreshold>
    11. <pattern>yyyyMMddpattern>
    12. <autoRollAtTime>00:00:00autoRollAtTime>
    13. <zipOlderThanNumDays>5zipOlderThanNumDays>
    14. <zipDateFormat>yyyyMMddzipDateFormat>
    15. log>
    16. service>

     注:如果启动不成功,可以把以上description里面的中文去掉

     三、C#文件上传下载

    1. public async void testupload()
    2. {
    3. try
    4. {
    5. MinioClient minio = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin");
    6. //桶名称
    7. string buckName = "202110001";
    8. //判断桶是否存在,如果不存在则创建桶,否则上传文件会异常
    9. var exists = await MinioHelper.BucketExists(minio, buckName);
    10. if (!exists)
    11. {
    12. //创建桶
    13. await MinioHelper.MakeBucket(minio, buckName);
    14. }
    15. //上传文件(桶下面可以自定义文件夹。如:1027/20211027001.jpg 则会创建一个1027文件夹)
    16. var result = await MinioHelper.FPutObject(minio, buckName, "1027/20211027001.png", "E:\\202110271417.png");
    17. //下载文件地址:192.168.90.128:9000+桶名称+文件名称
    18. }
    19. catch (Exception ex)
    20. {
    21. string str = ex.Message;
    22. }
    23. }

     四、minio文件操作帮助类

    1. public class MinioHelper
    2. {
    3. #region 操作存储桶
    4. /// 创建存储桶
    5. /// 创建存储桶
    6. ///
    7. /// 连接实例
    8. /// 存储桶名称
    9. /// 可选参数
    10. ///
    11. public async static Task<bool> MakeBucket(MinioClient minio, string bucketName, string loc = "us-east-1")
    12. {
    13. bool flag = false;
    14. try
    15. {
    16. bool found = await minio.BucketExistsAsync(bucketName);
    17. if (found)
    18. {
    19. throw new Exception(string.Format("存储桶[{0}]已存在", bucketName));
    20. }
    21. else
    22. {
    23. await minio.MakeBucketAsync(bucketName, loc);
    24. flag = true;
    25. }
    26. }
    27. catch (Exception e)
    28. {
    29. throw new Exception(e.Message);
    30. }
    31. return flag;
    32. }
    33. /// 列出所有的存储桶
    34. /// 列出所有的存储桶
    35. ///
    36. /// 连接实例
    37. ///
    38. public async static Taskbool, Minio.DataModel.ListAllMyBucketsResult>> ListBuckets(MinioClient minio)
    39. {
    40. bool flag = false;
    41. var list = new Minio.DataModel.ListAllMyBucketsResult();
    42. try
    43. {
    44. list = await minio.ListBucketsAsync();
    45. flag = true;
    46. //foreach (var bucket in list.Buckets)
    47. //{
    48. // Console.WriteLine($"{bucket.Name} {bucket.CreationDateDateTime}");
    49. //}
    50. }
    51. catch (Exception e)
    52. {
    53. throw new Exception(e.Message);
    54. }
    55. return Tuple.Create(flag, list);
    56. }
    57. /// 检查存储桶是否存在
    58. /// 检查存储桶是否存在
    59. ///
    60. /// 连接实例
    61. /// 存储桶名称
    62. ///
    63. public async static Task<bool> BucketExists(MinioClient minio, string bucketName)
    64. {
    65. bool flag = false;
    66. try
    67. {
    68. flag = await minio.BucketExistsAsync(bucketName);
    69. }
    70. catch (Exception e)
    71. {
    72. throw new Exception(e.Message);
    73. }
    74. return flag;
    75. }
    76. /// 删除一个存储桶
    77. /// 删除一个存储桶
    78. ///
    79. /// 连接实例
    80. /// 存储桶名称
    81. ///
    82. public async static Task<bool> RemoveBucket(MinioClient minio, string bucketName)
    83. {
    84. bool flag = false;
    85. try
    86. {
    87. bool found = await minio.BucketExistsAsync(bucketName);
    88. if (found)
    89. {
    90. await minio.RemoveBucketAsync(bucketName);
    91. flag = true;
    92. }
    93. else
    94. {
    95. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    96. }
    97. }
    98. catch (Exception e)
    99. {
    100. throw new Exception(e.Message);
    101. }
    102. return flag;
    103. }
    104. /// 列出存储桶里的对象
    105. /// 列出存储桶里的对象
    106. ///
    107. /// 连接实例
    108. /// 存储桶名称
    109. /// 对象的前缀
    110. /// true代表递归查找,false代表类似文件夹查找,以'/'分隔,不查子文件夹
    111. public static Tuple<bool, IObservable> ListObjects(MinioClient minio, string bucketName, string prefix = null, bool recursive = true)
    112. {
    113. bool flag = false;
    114. IObservable observable = null;
    115. try
    116. {
    117. var found = minio.BucketExistsAsync(bucketName);
    118. if (found.Result)
    119. {
    120. observable = minio.ListObjectsAsync(bucketName, prefix, recursive);
    121. flag = true;
    122. }
    123. else
    124. {
    125. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    126. }
    127. //IDisposable subscription = observable.Subscribe(
    128. // item => Console.WriteLine($"Object: {item.Key}"),
    129. // ex => Console.WriteLine($"OnError: {ex}"),
    130. // () => Console.WriteLine($"Listed all objects in bucket {bucketName}\n"));
    131. }
    132. catch (Exception e)
    133. {
    134. throw new Exception(e.Message);
    135. }
    136. return Tuple.Create(flag, observable);
    137. }
    138. /// 列出存储桶中未完整上传的对象
    139. /// 列出存储桶中未完整上传的对象
    140. ///
    141. /// 连接实例
    142. /// 存储桶名称
    143. /// 对象的前缀
    144. /// true代表递归查找,false代表类似文件夹查找,以'/'分隔,不查子文件夹
    145. ///
    146. public static Tuple<bool, IObservable> ListIncompleteUploads(MinioClient minio, string bucketName, string prefix = null, bool recursive = true)
    147. {
    148. bool flag = false;
    149. IObservable observable = null;
    150. try
    151. {
    152. var found = minio.BucketExistsAsync(bucketName);
    153. if (found.Result)
    154. {
    155. observable = minio.ListIncompleteUploads(bucketName, prefix, recursive);
    156. flag = true;
    157. }
    158. else
    159. {
    160. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    161. }
    162. //IDisposable subscription = observable.Subscribe(
    163. // item => Console.WriteLine($"OnNext: {item.Key}"),
    164. // ex => Console.WriteLine($"OnError: {ex.Message}"),
    165. // () => Console.WriteLine($"Listed the pending uploads to bucket {bucketName}"));
    166. }
    167. catch (Exception e)
    168. {
    169. throw new Exception(e.Message);
    170. }
    171. return Tuple.Create(flag, observable);
    172. }
    173. #endregion
    174. #region 存储桶策略
    175. ///
    176. /// 获取存储桶或者对象前缀的访问权限
    177. ///
    178. /// 连接实例
    179. /// 存储桶名称
    180. ///
    181. public async static Taskbool, string>> GetPolicy(MinioClient minio, string bucketName)
    182. {
    183. bool flag = false;
    184. string policyJson = string.Empty;
    185. try
    186. {
    187. var found = minio.BucketExistsAsync(bucketName);
    188. if (found.Result)
    189. {
    190. policyJson = await minio.GetPolicyAsync(bucketName);
    191. flag = true;
    192. }
    193. else
    194. {
    195. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    196. }
    197. }
    198. catch (Exception e)
    199. {
    200. throw new Exception(e.Message);
    201. }
    202. return Tuple.Create(flag, policyJson);
    203. }
    204. ///
    205. /// 针对存储桶和对象前缀设置访问策略
    206. ///
    207. /// 连接实例
    208. /// 存储桶名称
    209. ///
    210. public async static Task<bool> SetPolicy(MinioClient minio, string bucketName)
    211. {
    212. bool flag = false;
    213. try
    214. {
    215. bool found = await minio.BucketExistsAsync(bucketName);
    216. if (found)
    217. {
    218. 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"":""""}}]}}";
    219. await minio.SetPolicyAsync(bucketName, policyJson);
    220. flag = true;
    221. }
    222. else
    223. {
    224. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    225. }
    226. }
    227. catch (Exception e)
    228. {
    229. throw new Exception(e.Message);
    230. }
    231. return flag;
    232. }
    233. #endregion
    234. #region 存储桶通知
    235. ///
    236. /// 获取存储桶的通知配置
    237. ///
    238. /// 连接实例
    239. /// 存储桶名称
    240. ///
    241. private async static Taskbool, string>> GetBucketNotification(MinioClient minio, string bucketName)
    242. {
    243. bool flag = false;
    244. string Ret = string.Empty;
    245. try
    246. {
    247. bool found = await minio.BucketExistsAsync(bucketName);
    248. if (found)
    249. {
    250. BucketNotification notifications = await minio.GetBucketNotificationsAsync(bucketName);
    251. Ret = notifications.ToXML();
    252. flag = true;
    253. }
    254. else
    255. {
    256. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    257. }
    258. }
    259. catch (MinioException e)
    260. {
    261. throw new Exception(e.Message);
    262. }
    263. return Tuple.Create(flag, Ret);
    264. }
    265. ///
    266. /// 给存储桶设置通知
    267. ///
    268. /// 连接实例
    269. /// 存储桶名称
    270. ///
    271. private async static Task<bool> SetBucketNotification(MinioClient minio, string bucketName)
    272. {
    273. bool flag = false;
    274. try
    275. {
    276. bool found = await minio.BucketExistsAsync(bucketName);
    277. if (found)
    278. {
    279. BucketNotification notification = new BucketNotification();
    280. Arn topicArn = new Arn("aws", "sns", "us-west-1", "412334153608", "topicminio");
    281. TopicConfig topicConfiguration = new TopicConfig(topicArn);
    282. List events = new List() { EventType.ObjectCreatedPut, EventType.ObjectCreatedCopy };
    283. topicConfiguration.AddEvents(events);
    284. topicConfiguration.AddFilterPrefix("images");
    285. topicConfiguration.AddFilterSuffix("jpg");
    286. notification.AddTopic(topicConfiguration);
    287. QueueConfig queueConfiguration = new QueueConfig("arn:aws:sqs:us-west-1:482314153608:testminioqueue1");
    288. queueConfiguration.AddEvents(new List() { EventType.ObjectCreatedCompleteMultipartUpload });
    289. notification.AddQueue(queueConfiguration);
    290. await minio.SetBucketNotificationsAsync(bucketName, notification);
    291. flag = true;
    292. }
    293. else
    294. {
    295. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    296. }
    297. }
    298. catch (MinioException e)
    299. {
    300. throw new Exception(e.Message);
    301. }
    302. return flag;
    303. }
    304. ///
    305. /// 删除存储桶上所有配置的通知
    306. ///
    307. /// 连接实例
    308. /// 存储桶名称
    309. ///
    310. private async static Task<bool> RemoveAllBucketNotifications(MinioClient minio, string bucketName)
    311. {
    312. bool flag = false;
    313. try
    314. {
    315. bool found = await minio.BucketExistsAsync(bucketName);
    316. if (found)
    317. {
    318. await minio.RemoveAllBucketNotificationsAsync(bucketName);
    319. flag = true;
    320. }
    321. else
    322. {
    323. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    324. }
    325. }
    326. catch (MinioException e)
    327. {
    328. throw new Exception(e.Message);
    329. }
    330. return flag;
    331. }
    332. #endregion
    333. #region 操作文件对象
    334. ///
    335. /// 从桶下载文件到本地
    336. ///
    337. /// 连接实例
    338. /// 存储桶名称
    339. /// 存储桶里的对象名称
    340. /// 本地路径
    341. ///
    342. ///
    343. public async static Task<bool> FGetObject(MinioClient minio, string bucketName, string objectName, string fileName, ServerSideEncryption sse = null)
    344. {
    345. bool flag = false;
    346. try
    347. {
    348. bool found = await minio.BucketExistsAsync(bucketName);
    349. if (found)
    350. {
    351. if (File.Exists(fileName))
    352. {
    353. File.Delete(fileName);
    354. }
    355. await minio.GetObjectAsync(bucketName, objectName, fileName, sse).ConfigureAwait(false);
    356. flag = true;
    357. }
    358. else
    359. {
    360. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    361. }
    362. }
    363. catch (MinioException e)
    364. {
    365. throw new Exception(e.Message);
    366. }
    367. return flag;
    368. }
    369. ///
    370. /// 上传本地文件至存储桶
    371. ///
    372. /// 连接实例
    373. /// 存储桶名称
    374. /// 存储桶里的对象名称
    375. /// 本地路径
    376. ///
    377. public async static Task<bool> FPutObject(MinioClient minio, string bucketName, string objectName, string fileName)
    378. {
    379. bool flag = false;
    380. try
    381. {
    382. bool found = await minio.BucketExistsAsync(bucketName);
    383. if (found)
    384. {
    385. await minio.PutObjectAsync(bucketName, objectName, fileName, contentType: "application/octet-stream");
    386. flag = true;
    387. }
    388. else
    389. {
    390. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    391. }
    392. }
    393. catch (MinioException e)
    394. {
    395. throw new Exception(e.Message);
    396. }
    397. return flag;
    398. }
    399. #endregion
    400. #region Presigned操作
    401. /// 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
    402. /// 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
    403. ///
    404. /// 连接实例
    405. /// 存储桶名称
    406. /// 存储桶里的对象名称
    407. /// 失效时间(以秒为单位),默认是7天,不得大于七天
    408. /// 额外的响应头信息,支持response-expires、response-content-type、response-cache-control、response-content-disposition
    409. ///
    410. public async static Taskbool, string>> PresignedGetObject(MinioClient minio, string bucketName, string objectName, int expiresInt = 1000)
    411. {
    412. bool flag = false;
    413. string Ret = string.Empty;
    414. try
    415. {
    416. bool found = await minio.BucketExistsAsync(bucketName);
    417. if (found)
    418. {
    419. var reqParams = new Dictionary<string, string> { { "response-content-type", "application/json" } };
    420. string presignedUrl = await minio.PresignedGetObjectAsync(bucketName, objectName, expiresInt, reqParams);
    421. Ret = presignedUrl;
    422. flag = true;
    423. }
    424. else
    425. {
    426. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    427. }
    428. }
    429. catch (Exception e)
    430. {
    431. throw new Exception(e.Message);
    432. }
    433. return Tuple.Create(flag, Ret);
    434. }
    435. /// 生成一个给HTTP PUT请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
    436. /// 生成一个给HTTP PUT请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
    437. ///
    438. /// 连接实例
    439. /// 存储桶名称
    440. /// 存储桶里的对象名称
    441. /// 失效时间(以秒为单位),默认是7天,不得大于七天
    442. ///
    443. public async static Taskbool, string>> PresignedPutObject(MinioClient minio, string bucketName, string objectName, int expiresInt = 1000)
    444. {
    445. bool flag = false;
    446. string Ret = string.Empty;
    447. try
    448. {
    449. bool found = await minio.BucketExistsAsync(bucketName);
    450. if (found)
    451. {
    452. string presignedUrl = await minio.PresignedPutObjectAsync(bucketName, objectName, expiresInt);
    453. Ret = presignedUrl;
    454. flag = true;
    455. }
    456. else
    457. {
    458. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    459. }
    460. }
    461. catch (Exception e)
    462. {
    463. throw new Exception(e.Message);
    464. }
    465. return Tuple.Create(flag, Ret);
    466. }
    467. /// 允许给POST请求的presigned URL设置策略,比如接收对象上传的存储桶名称的策略,key名称前缀,过期策略。
    468. /// 允许给POST请求的presigned URL设置策略,比如接收对象上传的存储桶名称的策略,key名称前缀,过期策略。
    469. ///
    470. /// 连接实例
    471. /// 对象的post策略
    472. ///
    473. public async static Taskbool, string, Dictionary<string, string>>> PresignedPostPolicy(MinioClient minio)
    474. {
    475. bool flag = false;
    476. Tuple<string, Dictionary<string, string>> tdic = null;
    477. try
    478. {
    479. PostPolicy form = new PostPolicy();
    480. DateTime expiration = DateTime.UtcNow;
    481. form.SetExpires(expiration.AddDays(10));
    482. form.SetKey("my-objectname");
    483. form.SetBucket("my-bucketname");
    484. Tuple<string, Dictionary<string, string>> tuple = await minio.PresignedPostPolicyAsync(form);
    485. tdic = tuple;
    486. flag = true;
    487. //string curlCommand = "curl -X POST ";
    488. //foreach (KeyValuePair pair in tuple.Item2)
    489. //{
    490. // curlCommand = curlCommand + $" -F {pair.Key}={pair.Value}";
    491. //}
    492. //curlCommand = curlCommand + " -F file=@/etc/bashrc " + tuple.Item1; // https://s3.amazonaws.com/my-bucketname";
    493. }
    494. catch (Exception e)
    495. {
    496. throw new Exception(e.Message);
    497. }
    498. return Tuple.Create(flag, tdic.Item1, tdic.Item2);
    499. }
    500. #endregion
    501. #region 操作对象
    502. /// 返回对象数据的流
    503. /// 返回对象数据的流
    504. ///
    505. /// 连接实例
    506. /// 存储桶名称
    507. /// 存储桶里的对象名称
    508. /// 处理流的回调函数
    509. ///
    510. public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, Action callback)
    511. {
    512. bool flag = false;
    513. try
    514. {
    515. bool found = await minio.BucketExistsAsync(bucketName);
    516. if (found)
    517. {
    518. await minio.StatObjectAsync(bucketName, objectName);
    519. await minio.GetObjectAsync(bucketName, objectName, callback);
    520. flag = true;
    521. }
    522. else
    523. {
    524. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    525. }
    526. }
    527. catch (MinioException e)
    528. {
    529. throw new Exception(e.Message);
    530. }
    531. return flag;
    532. }
    533. /// 下载对象指定区域的字节数组做为流。offset和length都必须传
    534. /// 下载对象指定区域的字节数组做为流。offset和length都必须传
    535. ///
    536. /// 连接实例
    537. /// 存储桶名称
    538. /// 存储桶里的对象名称
    539. /// offset 是起始字节的位置
    540. /// length是要读取的长度
    541. /// 处理流的回调函数
    542. ///
    543. public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, long offset, long length, Action callback)
    544. {
    545. bool flag = false;
    546. try
    547. {
    548. bool found = await minio.BucketExistsAsync(bucketName);
    549. if (found)
    550. {
    551. await minio.StatObjectAsync(bucketName, objectName);
    552. await minio.GetObjectAsync(bucketName, objectName, offset, length, callback);
    553. flag = true;
    554. }
    555. else
    556. {
    557. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    558. }
    559. }
    560. catch (MinioException e)
    561. {
    562. throw new Exception(e.Message);
    563. }
    564. return flag;
    565. }
    566. /// 下载并将文件保存到本地文件系统
    567. /// 下载并将文件保存到本地文件系统
    568. ///
    569. /// 连接实例
    570. /// 存储桶名称
    571. /// 存储桶里的对象名称
    572. /// 本地文件路径
    573. ///
    574. public async static Task<bool> GetObjectAsync(MinioClient minio, string bucketName, string objectName, string fileName)
    575. {
    576. bool flag = false;
    577. try
    578. {
    579. bool found = await minio.BucketExistsAsync(bucketName);
    580. if (found)
    581. {
    582. if (File.Exists(fileName))
    583. {
    584. File.Delete(fileName);
    585. }
    586. await minio.StatObjectAsync(bucketName, objectName);
    587. await minio.GetObjectAsync(bucketName, objectName, fileName);
    588. flag = true;
    589. }
    590. else
    591. {
    592. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    593. }
    594. }
    595. catch (MinioException e)
    596. {
    597. throw new Exception(e.Message);
    598. }
    599. return flag;
    600. }
    601. /// 通过文件上传到对象中
    602. /// 通过文件上传到对象中
    603. ///
    604. /// 连接实例
    605. /// 存储桶名称
    606. /// 存储桶里的对象名称
    607. /// 要上传的本地文件名
    608. /// 文件的Content type,默认是"application/octet-stream"
    609. /// 元数据头信息的Dictionary对象,默认是null
    610. ///
    611. public async static Task<bool> PutObjectAsync(MinioClient minio, string bucketName, string objectName, string filePath, string contentType = "application/octet-stream", Dictionary<string, string> metaData = null)
    612. {
    613. bool flag = false;
    614. try
    615. {
    616. bool found = await minio.BucketExistsAsync(bucketName);
    617. if (found)
    618. {
    619. await minio.PutObjectAsync(bucketName, objectName, filePath, contentType, metaData);
    620. flag = true;
    621. }
    622. else
    623. {
    624. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    625. }
    626. }
    627. catch (Exception e)
    628. {
    629. throw new Exception(e.Message);
    630. }
    631. return flag;
    632. }
    633. /// 通过Stream上传对象
    634. /// 通过Stream上传对象
    635. ///
    636. /// 连接实例
    637. /// 存储桶名称
    638. /// 存储桶里的对象名称
    639. /// 要上传的Stream对象
    640. /// 流的大小
    641. /// 文件的Content type,默认是"application/octet-stream"
    642. /// 元数据头信息的Dictionary对象,默认是null
    643. ///
    644. 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)
    645. {
    646. bool flag = false;
    647. try
    648. {
    649. bool found = await minio.BucketExistsAsync(bucketName);
    650. if (found)
    651. {
    652. //byte[] bs = File.ReadAllBytes(fileName);
    653. //System.IO.MemoryStream filestream = new System.IO.MemoryStream(bs);
    654. await minio.PutObjectAsync(bucketName, objectName, data, size, contentType, metaData);
    655. flag = true;
    656. }
    657. else
    658. {
    659. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    660. }
    661. }
    662. catch (MinioException e)
    663. {
    664. throw new Exception(e.Message);
    665. }
    666. return flag;
    667. }
    668. /// 获取对象的元数据
    669. /// 获取对象的元数据
    670. ///
    671. /// 连接实例
    672. /// 存储桶名称
    673. /// 存储桶里的对象名称
    674. ///
    675. public async static Task<bool> StatObject(MinioClient minio, string bucketName, string bucketObject)
    676. {
    677. bool flag = false;
    678. try
    679. {
    680. bool found = await minio.BucketExistsAsync(bucketName);
    681. if (found)
    682. {
    683. ObjectStat statObject = await minio.StatObjectAsync(bucketName, bucketObject);
    684. flag = true;
    685. }
    686. else
    687. {
    688. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    689. }
    690. }
    691. catch (MinioException e)
    692. {
    693. throw new Exception(e.Message);
    694. }
    695. return flag;
    696. }
    697. /// 从objectName指定的对象中将数据拷贝到destObjectName指定的对象
    698. /// 从objectName指定的对象中将数据拷贝到destObjectName指定的对象
    699. ///
    700. ///
    701. /// 源存储桶名称
    702. /// 源存储桶中的源对象名称
    703. /// 目标存储桶名称
    704. /// 要创建的目标对象名称,如果为空,默认为源对象名称
    705. /// 拷贝操作的一些条件Map
    706. ///
    707. ///
    708. ///
    709. 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)
    710. {
    711. bool flag = false;
    712. try
    713. {
    714. bool found = await minio.BucketExistsAsync(fromBucketName);
    715. if (!found)
    716. {
    717. throw new Exception(string.Format("源存储桶[{0}]不存在", fromBucketName));
    718. }
    719. bool foundtwo = await minio.BucketExistsAsync(destBucketName);
    720. if (!foundtwo)
    721. {
    722. throw new Exception(string.Format("目标存储桶[{0}]不存在", destBucketName));
    723. }
    724. await minio.CopyObjectAsync(fromBucketName, fromObjectName, destBucketName, destObjectName, copyConditions, null, sseSrc, sseDest);
    725. flag = true;
    726. }
    727. catch (MinioException e)
    728. {
    729. throw new Exception(e.Message);
    730. }
    731. return flag;
    732. }
    733. /// 删除一个对象
    734. /// 删除一个对象
    735. ///
    736. /// 连接实例
    737. /// 存储桶名称
    738. /// 存储桶里的对象名称
    739. ///
    740. public async static Task<bool> RemoveObject(MinioClient minio, string bucketName, string objectName)
    741. {
    742. bool flag = false;
    743. try
    744. {
    745. bool found = await minio.BucketExistsAsync(bucketName);
    746. if (found)
    747. {
    748. await minio.RemoveObjectAsync(bucketName, objectName);
    749. flag = true;
    750. }
    751. else
    752. {
    753. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    754. }
    755. }
    756. catch (MinioException e)
    757. {
    758. throw new Exception(e.Message);
    759. }
    760. return flag;
    761. }
    762. /// 删除多个对象
    763. /// 删除多个对象
    764. ///
    765. /// 连接实例
    766. /// 存储桶名称
    767. /// 含有多个对象名称的IEnumerable
    768. ///
    769. public static async Task<bool> RemoveObjects(MinioClient minio, string bucketName, List<string> objectsList)
    770. {
    771. bool flag = false;
    772. try
    773. {
    774. bool found = await minio.BucketExistsAsync(bucketName);
    775. if (found)
    776. {
    777. if (objectsList != null)
    778. {
    779. IObservable objectsOservable = await minio.RemoveObjectAsync(bucketName, objectsList).ConfigureAwait(false);
    780. flag = true;
    781. //IDisposable objectsSubscription = objectsOservable.Subscribe(
    782. // objDeleteError => Console.WriteLine($"Object: {objDeleteError.Key}"),
    783. // ex => Console.WriteLine($"OnError: {ex}"),
    784. // () =>
    785. // {
    786. // Console.WriteLine($"Removed objects in list from {bucketName}\n");
    787. // });
    788. //return;
    789. }
    790. }
    791. else
    792. {
    793. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    794. }
    795. }
    796. catch (MinioException e)
    797. {
    798. throw new Exception(e.Message);
    799. }
    800. return flag;
    801. }
    802. /// 删除一个未完整上传的对象
    803. /// 删除一个未完整上传的对象
    804. ///
    805. /// 连接实例
    806. /// 存储桶名称
    807. /// 存储桶里的对象名称
    808. ///
    809. public async static Task<bool> RemoveIncompleteUpload(MinioClient minio, string bucketName, string objectName)
    810. {
    811. bool flag = false;
    812. try
    813. {
    814. bool found = await minio.BucketExistsAsync(bucketName);
    815. if (found)
    816. {
    817. await minio.RemoveIncompleteUploadAsync(bucketName, objectName);
    818. flag = true;
    819. }
    820. else
    821. {
    822. throw new Exception(string.Format("存储桶[{0}]不存在", bucketName));
    823. }
    824. }
    825. catch (MinioException e)
    826. {
    827. throw new Exception(e.Message);
    828. }
    829. return flag;
    830. }
    831. #endregion
    832. }

  • 相关阅读:
    互融云供应链集采管理平台:助企业快速打造供应链金融生态圈
    maven jar依赖地址
    Buffer 与 拥塞控制
    【JAVA】顺序表与ArrayList
    Redis之String类型和Hash类型的介绍和案例应用
    软设上午题错题知识点2
    1076 Wifi密码
    前端之【数据可视化】
    CMakeLists.txt基础指令与cmake-gui生成VS项目的步骤
    聊聊Excel的大批量导入导出
  • 原文地址:https://blog.csdn.net/feritylamb/article/details/126246293