翼度科技»论坛 编程开发 .net 查看内容

Simple WPF: WPF实现一个MINIO等S3兼容对象存储上传文件的小工具

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。
创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧!
目的

之前在阿里云ECS 99元/年的活动实例上搭建了一个测试用的MINIO服务,以前都是直接当基础设施来使用的,这次准备自己学一下S3兼容API相关的对象存储开发,因此有了这个小工具。目前仅包含上传功能,后续计划开发一个类似图床的对象存储应用。
完整代码托管于Github:mrchipset/simple-wpf
包含的小知识点


  • 通过AWSSDK使用S3 API
  • 通过App.config对服务器的Endpoint和AccessKey进行设置
  • 使用异步的方法响应按钮事件

小工具的界面可以实现简单地选择文件上传到桶存储中。
实现过程


  • 创建一个WPF项目,并完成如上图的布局
  • 在项目中添加用户配置文件 App.config来保存服务调用的地址和访问密钥等信息
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3.         <appSettings>
  4.                 <add key="endpoint" value="YOUR_S3_ENDPOINT_URL"/>
  5.                 <add key="accessKey" value="YOUR_ACCESS_KEY"/>
  6.                 <add key="secretKey" value="YOUR_SECRET_KEY"/>
  7.         </appSettings>
  8. </configuration>
复制代码
编写一个方法,在程序启动的时候导入连接参数配置
  1. private void loadConfiguration()
  2. {
  3.     NameValueCollection appConfig = ConfigurationManager.AppSettings;
  4.     if (string.IsNullOrEmpty(appConfig["endpoint"]))
  5.     {
  6.         ConfigurationManager.AppSettings.Set("endpoint", "endpoint");
  7.         MessageBox.Show(this, "Endpoint is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
  8.         this.Close();
  9.         return;
  10.     }
  11.     if (string.IsNullOrEmpty(appConfig["accessKey"]))
  12.     {
  13.         MessageBox.Show(this, "AccessKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
  14.         this.Close();
  15.         return;
  16.     }
  17.     if (string.IsNullOrEmpty(appConfig["secretKey"]))
  18.     {
  19.         MessageBox.Show(this, "SecretKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
  20.         this.Close();
  21.         return;
  22.     }
  23.     _endpoint = appConfig["endpoint"];
  24.     _accessKey = appConfig["accessKey"];
  25.     _secretKey = appConfig["secretKey"];
  26. }
复制代码

  • 为按钮添加响应处理函数
    由于上传需要一定的时间来完成,因此我们用async 关键字修饰上传按钮的点击事件处理函数,这样即时在上传过程中UI界面的操作也不会卡顿。函数原型如下,如果对C#的异步操作不是很熟悉的同学可以参考这篇博文:C# 使用基本的async/await实现异步
  1. private async void uploadBtn_Click(object sender, RoutedEventArgs e)
  2. {
  3.     StringBuilder sb = new StringBuilder();
  4.     sb.AppendLine($"Bucket: {Bucket}");
  5.     sb.AppendLine($"File: {UploadFile}");
  6.     statusTxtBlk.Text = sb.ToString();
  7.     var ret = await UploadFileAsync();
  8.     if (ret)
  9.     {
  10.         statusTxtBlk.Text = "Upload Successfully!";
  11.     }
  12. }
复制代码

  • 编写上传函数
    现在到了本文最关键的一步,编写S3 Object上传接口。其实S3的接口都替我们封装好了,只需要按照官方demo的流程进行调用即可。
    先创建凭据对象和配置对象,然后创建客户端对象和上传请求,即可用客户端对象的上传方法进行上传。服务函数的完整代码如下:
  1. private async Task<bool> UploadFileAsync()
  2. {
  3.      var credentials = new BasicAWSCredentials(_accessKey, _secretKey);
  4.      var clientConfig = new AmazonS3Config
  5.      {
  6.          ForcePathStyle = true,
  7.          ServiceURL = _endpoint,
  8.      };
  9.      bool ret = true;
  10.      using (var client = new AmazonS3Client(credentials, clientConfig))
  11.      {
  12.          try
  13.          {
  14.              var putRequest = new PutObjectRequest
  15.              {
  16.                  BucketName = _bucket,
  17.                  FilePath = UploadFile
  18.              };
  19.              var response = await client.PutObjectAsync(putRequest);
  20.          }
  21.          catch(FileNotFoundException e)
  22.          {
  23.              ret = false;
  24.              this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = e.Message));
  25.          }
  26.          catch (AmazonS3Exception e)
  27.          {
  28.              ret = false;
  29.              if (e.ErrorCode != null &&
  30.                  (e.ErrorCode.Equals("InvalidAccessKeyId") ||
  31.              e.ErrorCode.Equals("InvalidSecurity")))
  32.              {
  33.                  this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = "Please check the provided AWS Credentials"));
  34.              } else
  35.              {
  36.                  this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = $"An error occurred with the message '{e.Message}' when writing an object"));
  37.              }
  38.          }   
  39.      }
  40.      return ret;
  41. }
复制代码
注意
MINIO 在使用S3函数时必须要在AmazonS3Config 中设置ForcePathStyle 为True 。
最终实现的效果


来源:https://www.cnblogs.com/mrchip/p/18293111
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具