You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
7.7 KiB
C#

using Infrastructure.Extensions;
using Infrastructure.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Minio;
using Minio.DataModel;
using Minio.DataModel.Args;
using Minio.Exceptions;
namespace Infrastructure.CloudSdk.minio;
public class MinioService
{
private IMinioClient _minioClient;
public string _bucketName;
public string endPoint;
public bool UseSSL;
public string AccessKey;
public string SecretKey;
public MinioService()
{
InitializeMinIOClient();
//EnsureBucketExistsAsync(_bucketName).Wait();
}
private void InitializeMinIOClient()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"}.json",
optional: true)
.AddEnvironmentVariables();
// 构建配置
var configuration = builder.Build();
_bucketName = configuration["Minio:BucketName"];
endPoint = configuration["Minio:Endpoint"];
UseSSL = configuration["Minio:UseSSL"].ToBool();
AccessKey = configuration["Minio:AccessKey"];
SecretKey = configuration["Minio:SecretKey"];
_minioClient = new MinioClient()
.WithEndpoint(endPoint)
.WithCredentials(AccessKey, SecretKey)
.Build();
}
/// <summary>
/// 创建存储桶(如果不存在)
/// </summary>
public async Task CreateBucketIfNotExists(string _bucketName)
{
var existsArgs = new BucketExistsArgs().WithBucket(_bucketName);
bool found = await _minioClient.BucketExistsAsync(existsArgs);
if (!found)
{
var makeArgs = new MakeBucketArgs().WithBucket(_bucketName);
await _minioClient.MakeBucketAsync(makeArgs);
Console.WriteLine($"Bucket {_bucketName} created.");
}
}
public async Task<string> GetMetaObject(string objectName, string bucketName)
{
if (string.IsNullOrEmpty(bucketName))
{
bucketName = _bucketName;
}
if (objectName.StartsWith("http"))
{
objectName = objectName.Replace($"http://{endPoint}/{_bucketName}/", "");
}
var statArgs = new StatObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName);
var meta = await _minioClient.StatObjectAsync(statArgs);
var md5 = meta.MetaData["md5"];
return md5; //
}
public async Task EnsureBucketExistsAsync(string bucketName)
{
var existsArgs = new BucketExistsArgs().WithBucket(bucketName);
var x = await _minioClient.BucketExistsAsync(existsArgs);
Console.WriteLine($" {bucketName} exist status: " + x);
// 如果存储桶不存在,则创建存储桶
if (!x)
{
var makeArgs = new MakeBucketArgs().WithBucket(bucketName);
await _minioClient.MakeBucketAsync(makeArgs);
}
}
/// <summary>
/// 下载文件
/// </summary>
public async Task DownLoadObject(string bucketName, string objectKey, string localDir, string objectETag,
CancellationToken token = default)
{
var index = objectKey.LastIndexOf("/", StringComparison.Ordinal);
if (index > 0)
{
var dir = Path.Combine(localDir, objectKey.Substring(0, index));
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
}
var localPath = Path.Combine(localDir, objectKey.Replace('/', Path.DirectorySeparatorChar));
var getArgs = new GetObjectArgs()
.WithBucket(string.IsNullOrEmpty(bucketName) ? _bucketName : bucketName)
.WithObject(objectKey)
.WithFile(localPath);
var stat = await _minioClient.GetObjectAsync(getArgs, token);
}
/// <summary>
/// 列出所有对象
/// </summary>
public async Task<IAsyncEnumerable<Item>> ListAllObject(string bucketName, string prefix, bool recursive,
CancellationToken token = default)
{
// Just list of objects
// Check whether 'mybucket' exists or not.
if (string.IsNullOrEmpty(bucketName))
{
bucketName = _bucketName;
}
var existsArgs = new BucketExistsArgs().WithBucket(bucketName);
var found = await _minioClient.BucketExistsAsync(existsArgs, token);
if (found)
{
var args = new ListObjectsArgs()
.WithBucket(bucketName)
.WithPrefix(prefix)
.WithRecursive(recursive);
return _minioClient.ListObjectsEnumAsync(args, token);
}
Console.WriteLine("mybucket does not exist");
throw new Exception("bucket not found");
}
/// <summary>
/// 删除文件
/// </summary>
public async Task DeleteFile(string objectName)
{
try
{
if (objectName.StartsWith("http"))
{
objectName = objectName.Replace($"http://{endPoint}/{_bucketName}/", "");
}
var deleteargs = new RemoveObjectArgs().WithBucket(_bucketName).WithObject(objectName);
await _minioClient.RemoveObjectAsync(deleteargs);
Console.WriteLine($"File {objectName} deleted.");
}
catch (MinioException ex)
{
Console.WriteLine($"MinIO Exception: {ex.Message}");
}
}
public async Task<string> UploadFile(IFormFile file, string bucketName)
{
try
{
if (string.IsNullOrEmpty(bucketName))
{
bucketName = _bucketName;
}
//判断桶是否存在
var beArgs = new BucketExistsArgs().WithBucket(bucketName);
bool found = await _minioClient.BucketExistsAsync(beArgs).ConfigureAwait(false);
if (!found)
{
var mbArgs = new MakeBucketArgs()
.WithBucket(bucketName);
await _minioClient.MakeBucketAsync(mbArgs).ConfigureAwait(false);
}
var suffix = Path.GetExtension(file.FileName);
var objectName = $"{GenerateId.GenerateOrderNumber()}{suffix}";
// 使用内存流上传
using var stream = new MemoryStream();
await file.CopyToAsync(stream);
stream.Position = 0;
var md5 = Md5.CalculateStreamMd5(stream);
stream.Position = 0;
var putArgs = new PutObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithStreamData(stream)
.WithObjectSize(stream.Length)
.WithHeaders(new Dictionary<string, string>()
{
//x-amz-meta-md5
["X-Amz-Meta-Md5"] = md5
})
.WithContentType("application/octet-stream");
//.WithContentType(file.ContentType);
await _minioClient.PutObjectAsync(putArgs);
return "http://" + endPoint + "/" + bucketName + "/" + objectName;
}
catch (Exception ex)
{
throw new Exception($"上传文件失败: {ex.Message}");
}
}
public async Task<string> GetObjectUrl(string bucket, string myobject)
{
PresignedGetObjectArgs args = new PresignedGetObjectArgs()
.WithBucket(bucket)
.WithObject(myobject)
.WithExpiry(60 * 60 * 24);
var url = await _minioClient.PresignedGetObjectAsync(args);
return url;
}
}