前言
使用MinIO的过程中,我们这里遇到个需求,系统需要预览3D文件,前端操作,用浏览3D文件的工具打开3D文件的目录即可实现在线预览功能,这个时候问题来了,MinIO上传文件后进行了编译,如下图
这个时候在想读取文件(比如xx\xx\bb.txt),是读取不到的,所以,要在上传文件的时候再其他文件夹内,把上传的文件保存下来,给前端读取使用。一开始想的是放到同文件夹下,但是测试发现,虽然MinIO上传的文件夹名字是bb.txt,但是保存的文件无法与bb.txt文件夹放到同一目录下。
第一步 开发同步文件的程序
新建一个WebApi项目,其中配置信息与上一篇文章一样,这里不在赘述,主要讲一下区别点
配置中的"BucketDirectory": "D:\\aaa\\bbb\\ccc",是指文件要保存的目录
保存文件的主要代码
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Minio;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MinIOTest.Controllers
{
public class MinioCallbackController : ControllerBase
{
private static string _bucketName = string.Empty;//"demo";//默认桶
private readonly MinioClient _client;
private readonly IConfiguration _configuration;
private readonly ILogger<MinioCallbackController> _logger;
public MinioCallbackController(MinioClient client,
IConfiguration configuration,
ILogger<MinioCallbackController> logger)
{
_client = client;
_configuration = configuration;
_bucketName = configuration["MinIO:Bucket"];
_logger = logger;
}
[Route("/path")] //这里不能随便改,要与webhook配置的路径对应
[HttpPost]
//public IActionResult Post([FromBody]Dictionary<string,object> args)
public async Task<IActionResult> CallBack([FromBody] object args)
{
try
{
//_logger.LogInformation("aaaaaaaaaaa");
string jsonStr = args.ToString();
var jsonObj = JsonConvert.DeserializeObject<Root>(jsonStr);
string bucketDirectory = _configuration["MinIO:BucketDirectory"];//文件保存目录
var pathAll = jsonObj.Key;//获取文件路径
var fileName = pathAll.Split('/').Last();
//新增
if (jsonObj.EventName.Contains("Put"))
{
if (!System.IO.File.Exists(bucketDirectory))
{
DirectoryInfo directoryInfo = new DirectoryInfo(bucketDirectory);
directoryInfo.Create();
}
var memoryStream = new MemoryStream();
var path = jsonObj.Key.Substring(pathAll.IndexOf('/') + 1, pathAll.Length - pathAll.IndexOf('/') - 1);
await _client.GetObjectAsync(_bucketName, path,
(stream) =>
{
stream.CopyTo(memoryStream);
});
using FileStream targetFileStream = new FileStream($"{bucketDirectory}\\{fileName}", FileMode.OpenOrCreate);
memoryStream.WriteTo(targetFileStream);
}
else if (jsonObj.EventName.Contains("Delete"))
{
var path = $"{bucketDirectory}\\{fileName}";
System.IO.File.Delete(path);
}
return Ok();
}
catch (System.Exception ex)
{
_logger.LogError($"ERROR:{ex}");
}
return null;
}
}
}
注意路由[Route("/path")],这里是一个路径,要与下面配置Webhook时的路径一致。
Root类
这个实体写复杂了,其实只要第一层结构就行,这里往里面加了好几层,按实际情况来吧。
using MinIOTest;
using System.Collections.Generic;
namespace MinIOTest
{
public class ValueKind
{
}
public class UserIdentity
{
/// <summary>
///
/// </summary>
public string principalId { get; set; }
}
public class @object
{
/// <summary>
///
/// </summary>
public string key { get; set; }
/// <summary>
///
/// </summary>
public int size { get; set; }
/// <summary>
///
/// </summary>
public string eTag { get; set; }
/// <summary>
///
/// </summary>
public string contentType { get; set; }
/// <summary>
///
/// </summary>
public object userMetadata { get; set; }
/// <summary>
///
/// </summary>
public string sequencer { get; set; }
}
public class S3
{
/// <summary>
///
/// </summary>
public string s3SchemaVersion { get; set; }
/// <summary>
///
/// </summary>
public string configurationId { get; set; }
/// <summary>
///
/// </summary>
public object bucket { get; set; }
/// <summary>
///
/// </summary>
public @object @object { get; set; }
}
public class Source
{
/// <summary>
///
/// </summary>
public string host { get; set; }
/// <summary>
///
/// </summary>
public string port { get; set; }
/// <summary>
///
/// </summary>
public string userAgent { get; set; }
}
public class RecordsItem
{
/// <summary>
///
/// </summary>
public string eventVersion { get; set; }
/// <summary>
///
/// </summary>
public string eventSource { get; set; }
/// <summary>
///
/// </summary>
public string awsRegion { get; set; }
/// <summary>
///
/// </summary>
public string eventTime { get; set; }
/// <summary>
///
/// </summary>
public string eventName { get; set; }
/// <summary>
///
/// </summary>
public UserIdentity userIdentity { get; set; }
/// <summary>
///
/// </summary>
public object requestParameters { get; set; }
/// <summary>
///
/// </summary>
public object responseElements { get; set; }
/// <summary>
///
/// </summary>
public S3 s3 { get; set; }
/// <summary>
///
/// </summary>
public Source source { get; set; }
}
public class Root
{
/// <summary>
///
/// </summary>
public string EventName { get; set; }
/// <summary>
/// demo/工程图纸/001/bb.txt
/// </summary>
public string Key { get; set; }
/// <summary>
///
/// </summary>
public List<RecordsItem> Records { get; set; }
}
}
第二步 配置Webhook
当走到下面这一步的时候,要提前把服务打开,服务地址一般是http://192.168.x.xx:5000,服务不打开的话,下一步创建会失败,一般会有类似“远程服务拒绝连接”的提示。说的直白一点,就是上面写的同步文件的程序要运行起来。
创建完成后,是看不到新创建的内容的,需要把MinIO服务重启一下才行,重启服务方式见下图,点击重新启动,或者停止-开始(注意:部署的过程中发现一个问题,有些电脑需要重启服务,有些电脑不需要重启服务就能看到新建的Webhook,如果新建完成就能看到结果,那就别重启服务了)
如果服务正常连接,状态显示online
如果服务异常,显示offline,这种情况一般是服务没启动起来,需要检查服务
保存完成后,在这里可以看到新建的事件
在代码里加上断点,当上传文件或下载文件的时候,会命中断点,可以查看相关参数。
上一篇:MinIO (二) .net core中实现上传下载