一、写在前面
MinIO是一个非常好用的免费的开源的对象存储服务器,具体的安装教程,可参考我得博客:五分钟带你拥有一台自己的对象存储服务器
二、 编写代码
2.1、新建一个.NetCore6的项目,在appsetting.json中配置minio的服务器ip、账号、密码。
"MinIO": {
"Endpoint": "ip:9000",
"AccessKey": "admin123",
"SecretKey": "admin123456"
}
2.2、在program.cs中注册minio客户端
var minio = builder.Configuration.GetSection("MinIO");
builder.Services.AddSingleton<IMinioClient>(new MinioClient()
.WithEndpoint(minio["Endpoint"])
.WithCredentials(minio["AccessKey"], minio["SecretKey"])
.Build());
2.3、新建MinioFileService服务类,编写文件上传下载代码。
public class MinioFileService
{
private readonly IMinioClient minioClient;
private static string bucketName = "kecheng";
private readonly MongoService mongoService;
private readonly ILogger<UserController> logger;
public MinioFileService(IMinioClient minioClient, MongoService mongoService, ILogger<UserController> logger)
{
this.minioClient = minioClient;
this.mongoService = mongoService;
this.logger = logger;
}
public async Task<string> Upload(IFormFile file)
{
try
{
logger.LogInformation("文件开始上传");
string uploadsPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "uploads");
if (!Directory.Exists(uploadsPath))
{
Directory.CreateDirectory(uploadsPath);
}
string fileName = file.FileName;
string filePath = Path.Combine(uploadsPath, fileName);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
string fileExtension = Path.GetExtension(fileName);
string newFileName = null;
int counter = 1;
while (File.Exists(filePath))
{
//重新命名文件
string Name = $"{fileNameWithoutExtension}_{counter}{fileExtension}";
filePath = Path.Combine(uploadsPath, Name);
newFileName = Path.GetFileNameWithoutExtension(filePath);
counter++;
}
if (newFileName == null)
{
newFileName = Path.GetFileNameWithoutExtension(fileName);
}
using (var stream = new FileStream(filePath, FileMode.Create))
{
file.CopyTo(stream);
}
AddFileInfo(filePath, Path.GetFileNameWithoutExtension(fileName), newFileName);
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 objectName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var putObjectArgs = new PutObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithFileName(filePath)
.WithContentType(file.ContentType);
await minioClient.PutObjectAsync(putObjectArgs).ConfigureAwait(false);
return objectName;
}
catch (Exception ex)
{
// 处理异常
throw new ApplicationException("文件上传失败", ex);
}
}
/// <summary>
/// 获取桶列表
/// </summary>
/// <returns></returns>
public async Task<List<string>> GetBuckets()
{
var list = await minioClient.ListBucketsAsync().ConfigureAwait(false);
var buckets = list.Buckets.Select(b => b.Name).ToList();
return buckets;
}
/// <summary>
/// 文件信息入库
/// </summary>
/// <param name="filePath"></param>
/// <param name="name1">前端展示文件名</param>
/// <param name="name2">真实的文件名</param>
/// <returns></returns>
public FileInfotmation AddFileInfo(string filePath, string name1, string name2)
{
FileInfotmation fileInformation = new FileInfotmation()
{
Id = ObjectId.GenerateNewId().ToString(),
FileExtension = Path.GetExtension(filePath),
FileName1 = name2,
FileType = DetermineFileType(Path.GetExtension(filePath)),
FileName2 = name1
};
mongoService.GetFileInformationCollection().InsertOne(fileInformation);
return fileInformation;
}
/// <summary>
/// 下载接口
/// </summary>
/// <returns></returns>
public async Task DownLoad()
{
try
{
StatObjectArgs statObjectArgs = new StatObjectArgs()
.WithBucket(bucketName)
.WithObject("替换你上传到minio服务器中生成的objectName");
await minioClient.StatObjectAsync(statObjectArgs);
GetObjectArgs getObjectArgs = new GetObjectArgs()
.WithBucket(bucketName)
.WithObject("替换你上传到minio服务器中生成的objectName")
.WithFile("D:\\photo.jpg"); //替换你实际的文件输出路径
await minioClient.GetObjectAsync(getObjectArgs);
}
catch(MinioException e)
{
Console.Out.WriteLine("Error occurred:" + e);
}
}
/// <summary>
/// 后缀名枚举
/// </summary>
/// <param name="fileExtension"></param>
/// <returns></returns>
public string DetermineFileType(string fileExtension)
{
HashSet<string> supportedImageExtensions = new HashSet<string>
{
".jpg",".jpeg", ".png",".gif",".bmp",".tiff",".tif",".svg",".webp", ".ico"
};
HashSet<string> supportedVideoExtensions = new HashSet<string>
{
".mp4",".avi",".mkv",".mov",".wmv",".flv",".webm"
};
HashSet<string> supportedDocumentExtensions = new HashSet<string>
{
".doc",".docx",".pdf",".txt",".ppt",".pptx",".xls",".xlsx",
};
if (supportedDocumentExtensions.Contains(fileExtension.ToLower()))
{
return FileType.document.ToString();
}
else if (supportedImageExtensions.Contains(fileExtension.ToLower()))
{
return FileType.image.ToString();
}
else if (supportedVideoExtensions.Contains(fileExtension.ToLower()))
{
return FileType.video.ToString();
}
else
{
return FileType.other.ToString();
}
}
}
FileInformation.cs类
public class FileInfotmation
{
/// <summary>
/// id
/// </summary>
[BsonId]
public string Id { get; set; }
/// <summary>
/// 文件名称(真实的文件名)
/// </summary>
public string FileName1 { get; set; }
/// <summary>
/// 文件类型
/// </summary>
public string FileType { get; set; }
/// <summary>
/// 文件后缀
/// </summary>
public string FileExtension { get; set; }
/// <summary>
/// 给前端展示的文件名(上传相同文件的情况下)
/// </summary>
public string FileName2 { get; set; }
}
/// <summary>
/// 文件类型枚举类
/// </summary>
public enum FileType
{
/// <summary>
/// 视频文件
/// </summary>
video,
/// <summary>
/// 文档文件
/// </summary>
document,
/// <summary>
/// 图片文件
/// </summary>
image,
/// <summary>
/// // Python源文件
/// </summary>
PythonSourceFile,
/// <summary>
/// // MALTAB脚本文件
/// </summary>
MATLABScriptFile,
/// <summary>
/// // dll文件
/// </summary>
DLLFile,
/// <summary>
/// 其他类型文件
/// </summary>
other
}
数据库我使用的是mongodb,关于.NetCore连接mongodb可参考我的博客:五分钟带你快速掌握.NetCore6整合MongoDB
三、测试验证
3.1、注册MinioFileService服务
3.2、编写FileController控制器。
[Route("api/[controller]/[action]")]
[ApiController]
public class FileController : ControllerBase
{
private readonly MinioFileService fileService;
public FileController(MinioFileService fileService)
{
this.fileService = fileService;
}
/// <summary>
/// 文件上传
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
try
{
var fileName = await fileService.Upload(file);
return Ok(new { FileName = fileName });
}
catch (Exception ex)
{
return BadRequest(new { Message = ex.Message });
}
}
/// <summary>
/// 获取桶列表
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> GetBuckets()
{
var backets = await fileService.GetBuckets();
return Ok(backets);
}
[HttpPost]
public async Task<IActionResult> Download()
{
await fileService.DownLoad();
return Ok("下载成功");
}
}
3.3、运行代码,swagger测试
3.4、打开minio客户端