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(); } /// /// 创建存储桶(如果不存在) /// 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 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); } } /// /// 下载文件 /// 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); } /// /// 列出所有对象 /// public async Task> 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"); } /// /// 删除文件 /// 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 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() { //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 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; } }