CentOS7安装MinIO教程,并在C#客户端WPF中实现监控上传进度
MinIO的详细介绍可以参考官网(https://min.io/product/overview)。
简单来说它是一个实现了AWS S3标准的100%开源的,可商用的( Apache V2 license),高性能的分布式对象存储管理系统。
AWS S3是什么(https://zhuanlan.zhihu.com/p/112057573):
- 提供了统一的接口 REST/SOAP 来统一访问任何数据
- 对 S3 来说,存在里面的数据就是对象名(键),和数据(值)
- 不限量,单个文件最高可达 5TB
- 高速。每个 bucket 下每秒可达 3500 PUT/COPY/POST/DELETE 或 5500 GET/HEAD 请求
- 具备版本,权限控制能力
- 具备数据生命周期管理能力
这次主要介绍CentOS7如何安装MinIO,以及C#如何使用MinIO的.NET SDK来上传文件(显示上传进度)。
首先安装好CentOS7 64位操作系统,然后在/usr/local下新建一个minio目录,在minio目录下新建三个子文件夹,分别是:
bin 用来保存minio的主程序
data 用来保存用户上传的文件
etc 用来保存minio的配置文件
然后新建MinIO运行所需的系统组和用户
groupadd -g minio
useradd -r -M -u -g -c "Minio User" -s /sbin/nologin minio
建立了一个组ID是2020,名称是minio的系统组,然后添加了一个不能登录的名称是minio,所属组ID是2020并且个人ID也是2020的系统用户。
MinIO默认提供的http访问端口是9000,我们提前在防火墙里把9000端口打开
firewall-cmd --zone=public --add-port=/tcp --permanent
firewall-cmd --reload
同时我们需要给MinIO挂载要给存储空间比较大的磁盘用来存储文件
执行lvdisplay找到比较大的分区,挂载给/usr/local/minio目录
运行
mount /dev/centos/home /usr/local/minio
把这个200多G的逻辑卷挂载给minio的目录。
同时为了重启后自动挂载,我们需要执行以下代码
vim /etc/fstab
把centos-home这句换成以下内容,保存退出,就可以让系统重启后自动挂载空间到/usr/local/minio目录了
/dev/mapper/centos-home /usr/local/minio xfs defaults
然后我们运行lsblk就可以看到磁盘空间正确挂载在minio目录下了
从官网(或者通过下载工具下载到本地后上传)下载(https://min.io/download#/linux)到CentOS的/usr/local/minio/bin目录下
其中第二句(chmod +x minio)等把minio文件移动到/usr/local/minio/bin后在执行
第三句先不要执行
下面我们建立MinIO的配置文件
vim /usr/local/minio/etc/minio.conf
写入以下内容(--address后面的IP 是CentOS的IP地址)
MINIO_VOLUMES="/usr/local/minio/data"
MINIO_OPTS="-C /usr/local/minio/etc --address 192.168.127.131:9000
建立MinIO的service文件,让它随系统启动而启动
vim /etc/systemd/system/minio.service
写入以下内容
[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/minio/bin/minio [Service]
# User and group
User=minio
Group=minio EnvironmentFile=/usr/local/minio/etc/minio.conf
ExecStart=/usr/local/minio/bin/minio server $MINIO_OPTS $MINIO_VOLUMES # Let systemd restart this service always
Restart=always # Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE= # Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no [Install]
WantedBy=multi-user.target
然后我们启动MinIO
systemctl enable minio.service
systemctl start minio.service
systemctl status minio.service
启动正常后,我们访问http://192.168.127.131:9000就应该可以看到web管理端的登录界面
我们可以通过下面的命令来获取到默认的登录名和密码(minioadmin)
cat /usr/local/minio/data/.minio.sys/config/config.json
如果要自定义登录名和密码,可以在/usr/local/minio/etc/minio.conf中增加两个配置内容
MINIO_ACCESS_KEY="登录名"
MINIO_SECRET_KEY="登录密码"
至此,MinIO的安装就介绍完毕,下面是本文重点,C#中使用WPF客户端如何获取文件上传时的进度。
首先新建一个项目MinIO,项目类型是WPF,项目的.NET版本是4.6
引用官方的Minio .NET SDK以及其它一些需要的类库
在项目的根目录添加一个nlog.config并设置为较新时复制,内容如下(主要用来做一些日志记录):
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Info">
<targets>
<default-target-parameters xsi:type="File" createDirs="true" keepFileOpen="true" autoFlush="false" openFileFlushTimeout="10" openFileCacheTimeout="30" archiveAboveSize="10240" archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8"/>
<target xsi:type="File" name="InfoFile" fileName="${basedir}/InfoLogs/log.txt" archiveFileName="${basedir}/InfoLogs/log.{#}.txt">
<layout xsi:type="JsonLayout">
<attribute name="counter" layout="${counter}" />
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message:format=message}" encode="false" />
</layout>
</target>
<target xsi:type="File" name="ErrorFile" fileName="${basedir}/ErrorLogs/log.txt" archiveFileName="${basedir}/ErrorLogs/log.{#}.txt">
<layout xsi:type="JsonLayout">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" encode="false" />
<attribute name="exception">
<layout xsi:type="JsonLayout">
<attribute name="callsite" layout="${callsite}" />
<attribute name="callsite-linenumber" layout="${callsite-linenumber} " />
</layout>
</attribute>
</layout>
</target>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="InfoFile" />
<logger name="*" minlevel="Error" writeTo="ErrorFile" />
</rules>
</nlog>
在使用过程中发现MinIO的.NET SDK中并没有回显上传进度的地方(如果有请告知),经过一些摸索,在它暴露的日志记录的地方获取到当前上传文件块的编号,通过MVVM的Messenger传递给主程序,主程序接收后计算出当前进度并显示出来。
我们在App.xaml中添加一个启动事件App_OnStartup,在启动的时候初始化一下Nlog,并定义一下MinIO上传时遇到大文件分块的默认值(5MB)
namespace MinIO
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
public static NLog.Logger NewNLog;
public static long MinimumPartSize = * 1024L * 1024L;//单次上传文件请求最大5MB private void App_OnStartup(object sender, StartupEventArgs e)
{
NewNLog = NLog.LogManager.GetLogger("MinIOLoger");
}
}
}
在MainWindow.xaml中我们添加一个按钮用来上传文件,一个TextBlock用来显示上传文件信息和进度
<Window x:Class="MinIO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MinIO"
mc:Ignorable="d"
DataContext="{Binding FileUploadViewModel,Source={StaticResource Locator}}"
Title="MainWindow" Height="450" Width="800" Loaded="MainWindow_OnLoaded">
<Grid>
<Button Content="上传文件" HorizontalAlignment="Left" Margin="47,51,0,0" VerticalAlignment="Top" Width="75" Click="ButtonUpload_Click"/>
<TextBlock HorizontalAlignment="Left" Margin="47,158,0,0" TextWrapping="Wrap" VerticalAlignment="Top">
<Run Text=" 文件名:"></Run>
<Run Text="{Binding Path=FileName}"></Run>
<Run Text=" "></Run> <Run Text="文件大小:"></Run>
<Run Text="{Binding Path=FileSize}"></Run>
<Run Text=" "></Run> <Run Text="上传进度:"></Run>
<Run Text="{Binding Path=UploadProcess}"></Run> </TextBlock> </Grid>
</Window>
同时我们定义一个ViewModel来实现文件上传信息变化时的通知(ViewModel目录中新建一个FileUploadViewModel.cs)
using System.ComponentModel; namespace MinIO.ViewModel
{
public class FileUploadViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; private string _filename { get; set; }
/// <summary>
/// 文件名
/// </summary>
public string FileName
{
get => _filename;
set
{
_filename = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FileName"));
}
} private long _fileSize { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public long FileSize
{
get => _fileSize;
set
{
_fileSize = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FileSize"));
}
} private long _partNumber { get; set; }
/// <summary>
/// 当前上传块
/// </summary>
public long PartNumber
{
get => _partNumber;
set
{
_partNumber = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PartNumber"));
}
} private long _totalParts { get; set; }
/// <summary>
/// 文件全部块数
/// </summary>
public long TotalParts
{
get => _totalParts;
set
{
_totalParts = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TotalParts"));
}
} private string _uploadProcess { get; set; }
/// <summary>
/// 上传进度展示
/// </summary>
public string UploadProcess
{
get => _uploadProcess;
set
{
_uploadProcess = value;
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("UploadProcess"));
}
}
}
}
同时为了能让MinIO根据不同的文件类型展示不同的图标,我们还需要建立一个ContentType对应关系类(ContentTypeHelper.cs)
using System.Collections.Generic; namespace MinIO.Helper
{
public static class ContentTypeHelper
{
private static readonly Dictionary<string,string> DictionaryContentType=new Dictionary<string, string>
{
{"default","application/octet-stream"},
{"bmp","application/x-bmp"},
{"doc","application/msword"},
{"docx","application/msword"},
{"exe","application/x-msdownload"},
{"gif","image/gif"},
{"html","text/html"},
{"jpg","image/jpeg"},
{"mp4","video/mpeg4"},
{"mpeg","video/mpg"},
{"mpg","video/mpg"},
{"ppt","application/x-ppt"},
{"pptx","application/x-ppt"},
{"png","image/png"},
{"rar","application/zip"},
{"txt","text/plain"},
{"xls","application/x-xls"},
{"xlsx","application/x-xls"},
{"zip","application/zip"},
};
/// <summary>
/// 根据文件扩展名(不含.)返回ContentType
/// </summary>
/// <param name="fileExtension">文件扩展名(不包含.)</param>
/// <returns></returns>
public static string GetContentType(string fileExtension)
{
return DictionaryContentType.ContainsKey(fileExtension) ? DictionaryContentType[fileExtension] : DictionaryContentType["default"];
}
}
}
我们需要新建一个实现MinIO中IRequestLogger接口的类(LogHelper.cs),用来接收日志信息通过处理日志信息,来计算出当前上传进度信息
using GalaSoft.MvvmLight.Messaging;
using Minio;
using Minio.DataModel.Tracing;
using System.Net; namespace MinIO.Helper
{
public class LogHelper : IRequestLogger
{
public void LogRequest(RequestToLog requestToLog, ResponseToLog responseToLog, double durationMs)
{
if (responseToLog.statusCode == HttpStatusCode.OK)
{
foreach (var header in requestToLog.parameters)
{
if (!string.Equals(header.name, "partNumber")) continue;
if(header.value==null) continue;
int.TryParse(header.value.ToString(), out var partNumber);//minio遇到上传文件大于5MB时,会进行分块传输,这里就是当前块的编号(递增)
Messenger.Default.Send(partNumber, "process");//发送给主界面计算上传进度
break;
}
}
}
}
}
在MainWindow初始化的时候初始化MinIO的配置信息,同时用MVVM的Messenger来接收当前上传的块编号,用来计算上传进度。
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;
using Minio;
using Minio.Exceptions;
using MinIO.Helper;
using MinIO.ViewModel;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows; namespace MinIO
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private static string _endpoint = "192.168.127.131:9000";//minio服务器地址
private static string _accessKey = "minioadmin";//授权登录账号
private static string _secretKey = "minioadmin";//授权登录密码
private static MinioClient _minioClient; public MainWindow()
{
InitializeComponent();
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
_minioClient = new MinioClient(_endpoint, _accessKey, _secretKey);
Messenger.Default.Register<int>(this, "process", obj =>
{
try
{
Debug.WriteLine($"当前块编号:{obj}");
if (obj == )
{
ViewModelLocator.Instance.FileUploadViewModel.UploadProcess = "0.00%";
return;
}
ViewModelLocator.Instance.FileUploadViewModel.PartNumber = obj;
ViewModelLocator.Instance.FileUploadViewModel.UploadProcess =
$"{(float)ViewModelLocator.Instance.FileUploadViewModel.PartNumber / ViewModelLocator.Instance.FileUploadViewModel.TotalParts:P2}";//计算文件上传进度
}
catch (Exception exception)
{
App.NewNLog.Error($"计算上传进度时出错:{exception}");
}
});
}
private void ButtonUpload_Click(object sender, RoutedEventArgs e)
{
var open = new OpenFileDialog
{
CheckFileExists = true,
CheckPathExists = true,
};
if (open.ShowDialog(this) == false)
{
return;
} ViewModelLocator.Instance.FileUploadViewModel.FileName = open.SafeFileName;
try
{
Dispatcher?.InvokeAsync(async () =>
{
await Run(_minioClient, "test", open.FileName, ViewModelLocator.Instance.FileUploadViewModel.FileName);
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
} private static async Task Run(MinioClient minio, string userBucketName, string uploadFilePath, string saveFileName)
{
var bucketName = userBucketName;
var location = "us-east-1";
var objectName = saveFileName;
var filePath = uploadFilePath;
var contentType = ContentTypeHelper.GetContentType(saveFileName.Substring(saveFileName.LastIndexOf('.') + ));
var file = new FileInfo(uploadFilePath); try
{
var found = await minio.BucketExistsAsync(bucketName);
if (!found)
{
await minio.MakeBucketAsync(bucketName, location);
} _minioClient.SetTraceOn(new LogHelper());//我们在上传开始的时候,打开日志,通过日志抛出的块编号来计算出当前进度 ViewModelLocator.Instance.FileUploadViewModel.FileSize = file.Length;
ViewModelLocator.Instance.FileUploadViewModel.TotalParts = file.Length / App.MinimumPartSize + ;//计算出文件总块数 await minio.PutObjectAsync(bucketName, objectName, filePath, contentType);//上传文件
Debug.WriteLine("Successfully uploaded " + objectName); }
catch (MinioException e)
{
App.NewNLog.Error($"File Upload Error: {e}");
Debug.WriteLine($"File Upload Error: {e.Message}");
}
finally
{
_minioClient.SetTraceOff();
}
}
}
}
具体效果如下:
至此,我们实现了CentOS7下安装MinIO,并且在C#客户端下展示文件上传进度的功能。
PS:代码还不完善,少了一个小于5M的时候,直接展示上传成功的代码。
CentOS7安装MinIO教程,并在C#客户端WPF中实现监控上传进度的更多相关文章
- centos7命令行和图形界面的相互切换(附centos7安装配置教程)
一.最近安装了centos7,发现在命令行和图形界面的相互切换命令上,与centos以往版本有很大不同,先整理如下,加深记忆. 1,centos7默认安装后,跟其他版本一样,启动默认进入图形界面: 2 ...
- MVC文件图片ajax上传轻量级解决方案,使用客户端JSAjaxFileUploader插件01-单文件上传
前段时间做了几个关于图片.文件上传的Demo,使用客户端Query-File-Upload插件和服务端Badkload组件实现多文件异步上传,比如"MVC文件上传04-使用客户端jQuery ...
- Java 客户端操作 FastDFS 实现文件上传下载替换删除
FastDFS 的作者余庆先生已经为我们开发好了 Java 对应的 SDK.这里需要解释一下:作者余庆并没有及时更新最新的 Java SDK 至 Maven 中央仓库,目前中央仓库最新版仍旧是 1.2 ...
- centos7安装ambari教程
ambari版本 :2.4.2 (不过各版本安装过程没啥差异) 目录: 为什么要用Ambari 概念概述 版本信息 原理简介 安装 创建集群 创建集群 手动修改配置 NameNode HA 安装Sma ...
- Wix 安装部署教程(十) --来,用WPF做个漂亮的安装界面
在上一篇中曾留下两个问题,.Net捆绑安装不触发以及路径选择的问题现在都已经解决,这段时间花的最多的地方还是WPF调样式上面,奈何WPF功力不够,暂时还是没有达到自己想要的效果.另外ViewModel ...
- git连接远程客户端,命令行窗口上传文件
1.git官网,下载安装git客户端 2.配置全局的name和email,生成key git config --global user.name XXX git config --global us ...
- 使用java调用fastDFS客户端进行静态资源文件上传
一.背景 上篇博客我介绍了FastDFS的概念.原理以及安装步骤,这篇文章我们来聊一聊如何在java中使用FastDFSClient进行静态资源的上传. 二.使用步骤 1.开发环境 spring+sp ...
- [SAP ABAP开发技术总结]客户端文本文件、Excel文件上传下载
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 如何在SecureCRT中给linux上传和下载文件 安装redis
首先建立文件 /download sz和rz命令无法用.则用以下1.和2.3步骤 需要上传或者下载,需要使用rz和sz命令.如果linux上没有这两个命令工具,则需要先安装.可以使用yum安装.运 ...
随机推荐
- 最大熵原理(The Maximum Entropy Principle)
https://wanghuaishi.wordpress.com/2017/02/21/%E5%9B%BE%E8%A7%A3%E6%9C%80%E5%A4%A7%E7%86%B5%E5%8E%9F% ...
- 数据可视化之DAX篇(一)Power BI时间智能函数如何处理2月29日的?
https://zhuanlan.zhihu.com/p/109964336 今年是闰年,有星友问我,在Power BI中,2月29日的上年同期是怎么计算的? 这是个好问题,正好梳理一下,Power ...
- 安装 VsCode 插件安装以及配置
安装vscode 官方网站 https://code.visualstudio.com/ 下载后 1.双击vscode.exe 2.选择 我接受 3.一路下一步,遇到方框就选4.点击 安装按钮 v ...
- 开源|如何开发一个高性能的redis cluster proxy?
文|曹佳俊 网易智慧企业资深服务端开发工程师 背 景 redis cluster简介 Redis cluster是redis官方提供集群方案,设计上采用非中心化的架构,节点之间通过gossip协 ...
- bzoj4512[Usaco2016 Jan] Build Gates
bzoj4512[Usaco2016 Jan] Build Gates 题意: 某人从农场的(0,0)出发,沿边界到处乱走,走过的地方会留下栅栏,等走完后问要在多少个栅栏上开门才能使整个农场连通,最多 ...
- Java多线程原理+基础知识(超级超级详细)+(并发与并行)+(进程与线程)1
Java多线程 我们先来了解两个概念!!!! 1.什么是并发与并行 2.什么是进程与线程 1.什么是并发与并行 1.1并行:两个事情在同一时刻发生 1.2并发:两个事情在同一时间段内发生 并发与并行的 ...
- Ethical Hacking - Web Penetration Testing(9)
SQL INJECTION Discovering SQLi in GET Inject by browser URL. Selecting Data From Database Change the ...
- Pull后产生多余的log(Merge branch 'master' of ...)
第一步: git reset --hard 73d0d18425ae55195068d39b3304303ac43b521a 第二步: git push -f origin feature/PAC_1 ...
- 高效C++:资源管理
C++中资源泄漏一直都是老大难的问题,特别是在嵌入式环境中,一点点的资源泄漏,加上长时间的运行们就会导致程序崩溃,这种问题定位非常困难,无规律偶发.解决问题的一种方式是使用特定工具检查内存泄漏,优点是 ...
- [并发编程] -- 内存模型(针对JSR-133内存模型)篇
并发编程模型 1.两个关键问题 1)线程之间如何通信 共享内存程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信 消息传递程之间没有公共状态,线程之间必须通过发送消息来显式进行通信 2) ...