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

simple,wpf,minio,s3 · 浏览次数 : 149

小编点评

## 小虎技术分享:基于WPF的简单S3对象存储应用 ### 简介 本文将介绍如何使用WPF创建一个简单的S3对象存储应用,该应用可以实现文件的上传、下载和管理等功能。 ### 准备工作 首先,您需要在阿里云ECS上搭建一个MINIO服务。接着,准备好以下信息: - ENDPOINT:S3服务的域名或IP地址 - ACCESS_KEY:访问S3服务的密钥 - SECRET_KEY:访问S3服务的密码 ### 创建WPF项目 1. 打开Visual Studio,创建一个新的WPF应用程序。 2. 在解决方案资源管理器中,右键单击“解决方案”,然后选择“添加” > “新建项目” > “WPF User Control”。 ### 设计用户界面 1. 在WPF用户控件中,添加一个文件选择按钮(例如,使用`System.Windows.Forms.CheckBox`)和一个上传按钮(例如,使用`System.Windows.Forms.Button`)。 2. 添加一个文本框(例如,使用`System.Windows.Forms.RichTextBox`),用于显示文件上传的状态。 ### 实现文件上传功能 1. 在用户控件的代码文件中,添加以下命名空间: ```csharp using Amazon; using Amazon.S3; using Amazon.S3.Model; ``` 2. 创建一个方法,用于加载配置文件中的S3参数: ```csharp private void loadConfiguration() { NameValueCollection appConfig = ConfigurationManager.AppSettings; if (string.IsNullOrEmpty(appConfig["endpoint"])) { ConfigurationManager.AppSettings.Set("endpoint", "your_s3_endpoint_url"); MessageBox.Show(this, "Endpoint is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error); this.Close(); return; } if (string.IsNullOrEmpty(appConfig["accessKey"])) { MessageBox.Show(this, "AccessKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error); this.Close(); return; } if (string.IsNullOrEmpty(appConfig["secretKey"])) { MessageBox.Show(this, "SecretKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error); this.Close(); return; } _endpoint = appConfig["endpoint"]; _accessKey = appConfig["accessKey"]; _secretKey = appConfig["secretKey"]; } ``` 3. 为上传按钮添加响应处理函数,并使用`async`关键字修饰: ```csharp private async void uploadBtn_Click(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); sb.AppendLine($"Bucket: {Bucket}"); sb.AppendLine($"File: {UploadFile}"); statusTxtBlk.Text = sb.ToString(); var ret = await UploadFileAsync(); if (ret) { statusTxtBlk.Text = "Upload Successfully!"; } } ``` 4. 编写上传函数,调用S3 API进行文件上传: ```csharp private async Task UploadFileAsync() { var credentials = new BasicAWSCredentials(_accessKey, _secretKey); var clientConfig = new AmazonS3Config { ForcePathStyle = true, ServiceURL = _endpoint, }; bool ret = true; using (var client = new AmazonS3Client(credentials, clientConfig)) { try { var putRequest = new PutObjectRequest { BucketName = _bucket, FilePath = UploadFile }; var response = await client.PutObjectAsync(putRequest); } catch (FileNotFoundException e) { ret = false; this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = e.Message)); } catch (AmazonS3Exception e) { ret = false; if (e.ErrorCode != null && (e.ErrorCode.Equals("InvalidAccessKeyId") || e.ErrorCode.Equals("InvalidSecurity"))) { this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = "Please check the provided AWS Credentials")); } else { this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = $@"An error occurred with the message '{e.Message}' when writing an object")); } } } return ret; } ``` 5. 注意:在使用S3函数时,必须在AmazonS3Config中设置ForcePathStyle为True。 6. 最终实现的效果是:用户可以在WPF界面中选择文件上传到S3存储中。

正文

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

目的

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

完整代码托管于Github:mrchipset/simple-wpf

包含的小知识点

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

cmrQLEN2KEddprIRAYxMvUX7FZCQQvCs6B8WpQ2RHNc.png

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

实现过程

  1. 创建一个WPF项目,并完成如上图的布局
  2. 在项目中添加用户配置文件 App.config来保存服务调用的地址和访问密钥等信息
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appSettings>
		<add key="endpoint" value="YOUR_S3_ENDPOINT_URL"/>
		<add key="accessKey" value="YOUR_ACCESS_KEY"/>
		<add key="secretKey" value="YOUR_SECRET_KEY"/>
	</appSettings>
</configuration>

编写一个方法,在程序启动的时候导入连接参数配置

private void loadConfiguration()
{
    NameValueCollection appConfig = ConfigurationManager.AppSettings;
    if (string.IsNullOrEmpty(appConfig["endpoint"]))
    {
        ConfigurationManager.AppSettings.Set("endpoint", "endpoint");
        MessageBox.Show(this, "Endpoint is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        this.Close();
        return;
    }

    if (string.IsNullOrEmpty(appConfig["accessKey"]))
    {
        MessageBox.Show(this, "AccessKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        this.Close();
        return;
    }

    if (string.IsNullOrEmpty(appConfig["secretKey"]))
    {
        MessageBox.Show(this, "SecretKey is not set in the App.Config", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        this.Close();
        return;
    }

    _endpoint = appConfig["endpoint"];
    _accessKey = appConfig["accessKey"];
    _secretKey = appConfig["secretKey"];
}
  1. 为按钮添加响应处理函数
    由于上传需要一定的时间来完成,因此我们用async 关键字修饰上传按钮的点击事件处理函数,这样即时在上传过程中UI界面的操作也不会卡顿。函数原型如下,如果对C#的异步操作不是很熟悉的同学可以参考这篇博文:C# 使用基本的async/await实现异步
private async void uploadBtn_Click(object sender, RoutedEventArgs e)
{
    StringBuilder sb = new StringBuilder();
    sb.AppendLine($"Bucket: {Bucket}");
    sb.AppendLine($"File: {UploadFile}");
    statusTxtBlk.Text = sb.ToString();
    var ret = await UploadFileAsync();
    if (ret)
    {
        statusTxtBlk.Text = "Upload Successfully!";
    }
}
  1. 编写上传函数
    现在到了本文最关键的一步,编写S3 Object上传接口。其实S3的接口都替我们封装好了,只需要按照官方demo的流程进行调用即可。
    先创建凭据对象和配置对象,然后创建客户端对象和上传请求,即可用客户端对象的上传方法进行上传。服务函数的完整代码如下:
 private async Task<bool> UploadFileAsync()
 {
     var credentials = new BasicAWSCredentials(_accessKey, _secretKey);

     var clientConfig = new AmazonS3Config
     {
         ForcePathStyle = true,
         ServiceURL = _endpoint,
     };

     bool ret = true;
     using (var client = new AmazonS3Client(credentials, clientConfig)) 
     {
         try
         {
             var putRequest = new PutObjectRequest
             {
                 BucketName = _bucket,
                 FilePath = UploadFile
             };
             var response = await client.PutObjectAsync(putRequest);
         }
         catch(FileNotFoundException e)
         {
             ret = false;
             this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = e.Message));
         }
         catch (AmazonS3Exception e)
         {
             ret = false;
             if (e.ErrorCode != null &&
                 (e.ErrorCode.Equals("InvalidAccessKeyId") ||
             e.ErrorCode.Equals("InvalidSecurity")))
             {
                 this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = "Please check the provided AWS Credentials"));
             } else
             {
                 this.Dispatcher.Invoke(new Action(() => this.statusTxtBlk.Text = $"An error occurred with the message '{e.Message}' when writing an object"));
             }
         }   
     }
     return ret;
 }

注意
MINIO 在使用S3函数时必须要在AmazonS3Config 中设置ForcePathStyleTrue

最终实现的效果

lO2tSD8ec3B25NI95FWqDaeHcBm33fDjvvyklqXAbL0.gif

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

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

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

Simple WPF: S3实现MINIO大文件上传并显示上传进度

早两天写了一篇S3简单上传文件的小工具,知乎上看到了一个问题问如何实现显示MINIO上传进度,因此拓展一下这个小工具能够在上传大文件时显示进度。

Simple WPF: WPF 实现按钮的长按,短按功能

实现了一个支持长短按得按钮组件,单击可以触发Click事件,长按可以触发LongPressed事件,长按松开时触发LongClick事件。还可以和自定义外观相结合,实现自定义的按钮外形。

Simple WPF: WPF自定义一个可以定义步长的SpinBox

通过WPF的按钮、文本输入框实现了一个简单的SpinBox数字输入用户组件并可以通过数据绑定数值和步长。本文中介绍了通过Xaml代码实现自定义组件的布局,依赖属性的定义和使用等知识点。

Simple WPF: WPF 自定义按钮外形

WPF的按钮提供了Template模板,可以通过修改Template模板中的内容对按钮的样式进行自定义。结合资源字典,可以将自定义资源在xaml窗口、自定义控件或者整个App当中调用

Simple WPF: WPF 透明窗体和鼠标事件穿透

一个自定义WPF窗体的解决方案,借鉴了吕毅老师的WPF制作高性能的透明背景的异形窗口一文,并在此基础上增加了鼠标穿透的功能。可以使得透明窗体的鼠标事件穿透到下层,在下层窗体中响应。

简单工厂模式( Simple Factory Pattern )

简单工厂模式(Simple Factory Pattern),在工厂类中对象决定创建出哪一种产品类的实例。这些产品类都实现了相同的接口,或者继承了相同的父类。 结构图 Factory(工厂角色):它是核心,负责实现创建所有实例的内部逻辑。在工厂类中,提供了一个静态方法,可以直接被外界直接调用,以创建

Simple Factory 简单工厂模式简介与 C# 示例【创建型3.1】【设计模式来了_3.1】

本文通过简单的实例对简单工厂模式进行了介绍。

Simple Date Format类到底为啥不是线程安全的?

摘要:我们就一起看下在高并发下Simple Date Format类为何会出现安全问题,以及如何解决Simple Date Format类的安全问题。 本文分享自华为云社区《【高并发】SimpleDateFormat类到底为啥不是线程安全的?》,作者:冰 河。 首先问下大家:你使用的Simple D

设计模式之简单工厂模式(学习笔记)

定义 简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它定义一个用于创建对象的接口,但由一个单独的类来实现实际创建的工作。简单工厂模式通过在一个类中集中管理对象的创建过程,可以减少客户端与具体类之间的耦合,使得代码结构更加清晰和易于维护。通过专门定义一个类来负责创建