微笑小生 发表于 2021-12-24 10:09

使用.NET CORE 实战minio文件服务器,部署、集成,可以直接使用哈


[*]这里使用的环境是 .net core 3.0以上版本   centos服务器一台

MiniO对象存储服务是一中开源的文件存储器,我这里是将minio放在docker下运行


[*]
第一步:首先需要在环境中安装docker容器 (这里大家可以百度一下安装docker容器,很简单) 这里还是给一个参考地址吧:https://www.runoob.com/docker/centos-docker-install.html
[*]
第二步:这里就可以直接安装minio了,这里的我是自定义安装,执行一下命令:docker run -d --restart always \-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v /mnt/data:/data \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin123456" \
minio/minio server /data --console-address ":9001"


说明一下: 9000和9001是端口号,如果被占用,可以使用其他的端口号, - v就是路径了,这里可以创建一个,或者使用其他的路径就好了下面就是用户名和密码,命令使用成功后,这里开源的minio会帮我们生成一个管理的客户端,使用外网IP加9001的端口访问
参数地址:http://docs.minio.org.cn/docs/master/minio-monitoring-guide
效果为:
   


以上部署好了,接下来就是在项目中集成minio文件服务器了,(这里帮公司省了一笔钱呢,可能现在有的公司还在用腾讯云、阿里云啥的{:1_918:})

废话不多说,直接上代码


[*]将部署好的Minio服务,绑定到项目上,实现文件的上传,返回相应的地址了

首先在文件Startup上添加一个依赖: 这里需要一个依赖包:Minio.AspNetCore
services.AddMinio(options =>
            {
                options.Endpoint = _config.GetSection("Startup")["Minio:Endpoint"];// 这里是在配置文件接口访问域名
                options.Region = _config.GetSection("Startup")["Minio:Region"];// 地址
                options.AccessKey = _config.GetSection("Startup")["Minio:AccessKey"];// 用户名
                options.SecretKey = _config.GetSection("Startup")["Minio:SecretKey"];   // 密码
               
            });

services.AddSingleton<IMinIOService, MinIOService>();

此时有人会问:MinIOService 这个文件是干嘛的,这里是帖主封装的一个Minio业务层 就是连接、压缩、文件策略等

/// <summary>
    /// 上传文件相关
    /// </summary>
    public class MinIOService : IMinIOService
    {
      public AppSetting _settings { get; }
      public IHostingEnvironment _hostingEnvironment { get; set; }
      public MinioClient _client { get; set; }
      public MinioOptions _minioOptions { get; set; }
      public MinIOService(IOptions<AppSetting> setting, IHostingEnvironment hostingEnvironment, MinioClient client, IOptions<MinioOptions> minioOptions)
      {
            _settings = setting.Value;
            _hostingEnvironment = hostingEnvironment;
            _client = client;
            _minioOptions = minioOptions.Value;
      }
      //获取图片的返回类型
      public static Dictionary<string, string> contentTypDict = new Dictionary<string, string> {
                {"bmp","image/bmp" },
                {"jpg","image/jpeg"},
                {"jpeg","image/jpeg"},
                {"jpe","image/jpeg"},
                {"png","image/png"},
                {"gif","image/gif"},
                {"ico","image/x-ico"},
                {"tif","image/tiff"},
                {"tiff","image/tiff"},
                {"fax","image/fax"},
                {"wbmp","image//vnd.wap.wbmp"},
                {"rp","image/vnd.rn-realpix"} };


      /// <summary>
      /// 上传图片
      /// </summary>
      /// <param name="file">文件</param>
      /// <returns></returns>

      public async Task<Result<FileModel>> UploadImageAsync(FormFileCollection file)
      {
            Result<FileModel> res = new Result<FileModel>(false, "上传失败");

            //获得文件扩展名
            string fileNameEx = System.IO.Path.GetExtension(file.FileName).Replace(".", "");

            //是否是图片,现在只能是图片上传 文件类型 或扩展名不一致则返回
            if (contentTypDict.Values.FirstOrDefault(c => c == file.ContentType.ToLower()) == null || contentTypDict.Keys.FirstOrDefault(c => c == fileNameEx) == null)
            {
                res.Msg = "图片格式不正确";
                return res;
            }
            else
                return await UploadAsync(file);
      }

      

      /// <summary>
      /// 上传
      /// </summary>
      /// <param name="file">文件</param>
      /// <returns></returns>

      public async Task<Result<FileModel>> UploadAsync(FormFileCollection file)
      {
            Result<FileModel> res = new Result<FileModel>(false, "上传失败");
            try
            {

                //存储桶名
                string bucketName = _settings.BucketName;

                FileModel fileModel = new FileModel();
                await CreateBucket(bucketName);
                var newFileName = CreateNewFileName(bucketName, file.FileName);
                await _client.PutObjectAsync(bucketName, newFileName, file.OpenReadStream(), file.Length,
                  file.ContentType);
                fileModel.Url = $"{_settings.FileURL}{newFileName}";

                //是否是图片,是图片进行压缩
                if (contentTypDict.Values.Contains(file.ContentType.ToLower()))
                {
                  string path = $"{_hostingEnvironment.ContentRootPath}/wwwroot/imgTemp/";
                  if (!Directory.Exists(Path.GetDirectoryName(path)))
                        Directory.CreateDirectory(Path.GetDirectoryName(path));

                  var bImageName = $"m_{newFileName}";
                  var savepath = $"{path}m_{newFileName}";//保存绝对路径
                  #region 保存原图到本地
                  using (FileStream fs = System.IO.File.Create(path + newFileName))
                  {
                        file.CopyTo(fs);
                        fs.Flush();
                  }
                  #endregion

                  #region 保存缩略图到本地
                  var bUrlRes = TencentCloudImageHelper.GetThumbnailImage(240, newFileName, path);
                  #endregion

                  //上传压缩图
                  if (bUrlRes.Res)
                  {
                        using (var sw = new FileStream(savepath, FileMode.Open))
                        {
                            await _client.PutObjectAsync(bucketName, bImageName, sw, sw.Length,
               "image/jpeg");
                            fileModel.BUrl = $"{_settings.FileURL}{bImageName}";
                        }

                        if (Directory.Exists(Path.GetDirectoryName(path)))
                            Directory.Delete(Path.GetDirectoryName(path), true);
                  }
                }
                res.Res = true;
                res.Msg = "上传成功";
                res.Data = fileModel;
                return res;
            }
            catch (Exception e)
            {

                return res;
            }
      }

      public async Task<Result<FileModel>> UploadPdf(Stream file)
      {
            Result<FileModel> res = new Result<FileModel>(false, "上传失败");
            try
            {
               
                //存储桶名
                string bucketName = _settings.BucketName;

                FileModel fileModel = new FileModel();
                await CreateBucket(bucketName);
                var newFileName = CreateNewFileName(bucketName, "授权书.pdf");
                await _client.PutObjectAsync(bucketName, newFileName, file, file.Length,
                  "application/pdf");
                fileModel.Url = $"{_settings.FileURL}{newFileName}";

                res.Res = true;
                res.Msg = "上传成功";
                res.Data = fileModel;
                return res;
            }
            catch (Exception e)
            {

                return res;
            }
      }

      private async Task CreateBucket(string bucketName)
      {
            var found = await _client.BucketExistsAsync(bucketName);
            if (!found)
            {
                await _client.MakeBucketAsync(bucketName);
                //设置只读策略
                var pObj = new
                {
                  Version = "2012-10-17",
                  Statement = new[]
                  {
                        new
                        {
                            Effect = "Allow",
                            Principal = new
                            {
                              AWS = new [] {"*"}
                            },
                            Action = new [] {"s3:GetBucketLocation", "s3:ListBucket"},
                            Resource = new []
                            {
                              $"arn:aws:s3:::{bucketName}"
                            }
                        },
                        new
                        {
                            Effect = "Allow",
                            Principal = new
                            {
                              AWS = new [] {"*"}
                            },
                            Action = new [] {"s3:GetObject"},
                            Resource = new []
                            {
                              $"arn:aws:s3:::{bucketName}/*"
                            }
                        }
                  }
                };
                var po = JsonSerializer.Serialize(pObj);
                await _client.SetPolicyAsync(bucketName, po);
            }
      }

      private string CreateNewFileName(string bucketName, string oldFileName)
      {
            var dt =Guid.NewGuid().ToString().Replace("-", "").Substring(10)+ DateTimeOffset.Now.ToUnixTimeSeconds();
            var extensions = Path.GetExtension(oldFileName);
            var newFileName = $"{bucketName}-{dt}{extensions}";
            return newFileName;
      }
    }


public interface IMinIOService
    {
      /// <summary>
      /// 上传
      /// </summary>
      /// <param name="file">文件</param>
      /// <returns></returns>
      Task<Result<FileModel>> UploadAsync(FormFileCollection file);

      /// <summary>
      /// 上传图片
      /// </summary>
      /// <param name="file">文件</param>
      /// <returns></returns>

      Task<Result<FileModel>> UploadImageAsync(FormFileCollection file);

      /// <summary>
      /// 上传pdf
      /// </summary>
      /// <param name="file"></param>
      /// <returns></returns>
      Task<Result<FileModel>> UploadPdf(Stream file);
    }


此时接口已经写完了,下面就是在控制器层写一个简单的调用接口吧,然后看看是否上传到你的MiniO对象存储服务上

可能有些配置没有给到,我的都是在配置文件中,比如一些存储桶名,文件对外访问域名等。。


[*]在控器层调用接口

/// <summary>
      /// 上传图片
      /// </summary>
      /// <returns></returns>
      
      public async Task<Result<FileModel>> AddImg(FormFileCollection file)
      {
            return await _minIOService.UploadImageAsync(file);
      }

以上如果有不懂的可以评论我,谢谢支持!!



zxxiaopi 发表于 2021-12-24 13:23

感谢分享

yunruifuzhu 发表于 2022-1-25 13:30

我用docker hub 上的 开了个容器,但控制中心帐号密码 minioadmin登不进去呢。是run的时候配还是 默认什么的,文档上也没写

微笑小生 发表于 2022-1-25 16:52

yunruifuzhu 发表于 2022-1-25 13:30
我用docker hub 上的 开了个容器,但控制中心帐号密码 minioadmin登不进去呢。是run的时候配还是 默认什么 ...

如果安装安装成功了。MINIO_ROOT_USER和MINIO_ROOT_PASSWORD 就是账户和密码,-v配置的就是日志目录,看看啥情况。我分享一下我的安装 docker run -d --restart always \
-p 7000:7000 \
-p 7001:7001 \
--name minio \
-v /mnt/data:/data \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin123456" \
minio/minio server /data --console-address ":7001"

我这个是没有问题的,端口改成了7000了

我们该成熟 发表于 2022-5-18 09:42

4个g的大文件如何弄?{:1_907:}
页: [1]
查看完整版本: 使用.NET CORE 实战minio文件服务器,部署、集成,可以直接使用哈