Files
MegghysAPI/Core/FileManager.cs
2025-02-25 22:28:49 +08:00

141 lines
5.7 KiB
C#

using MegghysAPI.Attributes;
using Minio;
using Minio.DataModel.Args;
namespace MegghysAPI.Core
{
internal class FileManager
{
private static IMinioClient minio = new MinioClient()
.WithEndpoint(Config.Instance.MinIOEndpoint)
.WithRegion(Config.Instance.MinIORegion)
.WithCredentials(Config.Instance.MinIOAccessKey, Config.Instance.MinIOSecretKey)
.WithSSL(false)
.Build();
public const string FavoritePath = "/Files/Favorite/";
[AutoInit("初始化文件服务")]
public static void Init()
{
}
public static async Task<string> DownloadFileAsync(string fileName, string path)
{
try
{
var temp = Path.Combine(Datas.TempFilePath, fileName);
if (File.Exists(temp))
return temp;
var result = await minio.GetObjectAsync(new Minio.DataModel.Args.GetObjectArgs()
.WithBucket(Config.Instance.MinIOBucket)
.WithObject(fileName)
.WithCallbackStream(stream =>
{
// 将下载流保存为本地文件
using var fileStream = File.Create(temp);
stream.CopyTo(fileStream);
}));
return temp;
}
catch (Exception ex)
{
Logs.Warn($"未能从储存空间下载文件: {path}{fileName}\r\n{ex}");
return null;
}
}
public static bool UploadBytes(byte[] data, string remotePath, string contentType = "application/octet-stream", bool overwrite = false)
{
using var stream = new MemoryStream(data);
return UploadStream(stream, remotePath, contentType, overwrite: overwrite);
}
public static async Task<bool> UploadStreamAsync(Stream stream, string remotePath, string contentType = "application/octet-stream", bool overwrite = false)
{
try
{
if (!overwrite && await ContainsFileAsync(remotePath))
return true;
// Upload a file to bucket.
var putObjectArgs = new PutObjectArgs()
.WithBucket(Config.Instance.MinIOBucket)
.WithStreamData(stream)
.WithObjectSize(stream.Length)
.WithObject(remotePath)
.WithContentType(contentType);
await minio.PutObjectAsync(putObjectArgs);
return true;
}
catch (Exception ex)
{
Logs.Warn($"未能向储存空间路径上传文件流 {remotePath}\r\n{ex}");
return false;
}
}
public static bool UploadStream(Stream stream, string remotePath, string contentType = "application/octet-stream", bool overwrite = false)
=> UploadStreamAsync(stream, remotePath, contentType, overwrite).Result;
/*public static async Task<FtpStatus> UploadFileAsync(string localFilePath, string remotePath = SetuPath, bool overwrite = false)
{
{
try
{
if (!File.Exists(localFilePath))
return false;
return await FTPConnection.UploadFile(localFilePath, remotePath, overwrite ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip);
}
catch (Exception ex)
{
Logs.Warn($"未能向储存空间路径上传文件 {localFilePath} => {remotePath}\r\n{ex}");
return FtpStatus.Failed;
}
}
}
public static FtpStatus UploadFile(string localFilePath, string remotePath = SetuPath, bool overwrite = false)
=> UploadFileAsync(localFilePath, remotePath, overwrite).Result;*/
public static async Task<string[]> ListFilesNameAsync(string path)
{
return (await ListFilesAsync(path)).Select(x => x.Name).ToArray();
}
public class MItem(Minio.DataModel.Item item) : Minio.DataModel.Item
{
public string Name { get; set; } = item.Key.Contains('/') ? item.Key[(item.Key.LastIndexOf('/') + 1)..] : item.Key;
}
public static async Task<MItem[]> ListFilesAsync(string path, bool recursive = false, bool includeUserMetadata = false)
{
try
{
var result = minio.ListObjectsEnumAsync(new ListObjectsArgs()
.WithBucket(Config.Instance.MinIOBucket)
.WithRecursive(recursive)
.WithIncludeUserMetadata(includeUserMetadata));
var fileList = new List<Minio.DataModel.Item>();
await foreach (var item in result)
{
fileList.Add(item);
}
return [.. fileList.Select(x => new MItem(x))];
}
catch (Exception ex)
{
Logs.Warn($"未能列出储存空间中 {path} 的文件\r\n{ex}");
return null;
}
}
public static async Task<bool> ContainsFileAsync(string path)
{
try
{
var stat = await minio.StatObjectAsync(
new StatObjectArgs()
.WithBucket(Config.Instance.MinIOBucket)
.WithObject(path)
);
return true;
}
catch
{
return false;
}
}
}
}