MinIO (二) .net core中实现上传下载

这篇文章里,我们介绍在.net core webapi项目中操作MinIO。

首先要创建一个桶,命名为demo

英文文档看不太顺畅,在网上找了一个api中文文档,可供参考

.NET Client API参考文档 - MinIO 帮助文档 - 开发文档 - 文江博客

创建个webapi项目,并添加Minio的NuGet包,这里我选3.1.13版本

将Minio注入进来,并将minio连接信息配置在appsetting,json文件中Startup.cs

cs 复制代码
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient();

    #region minio客户端注入
    var minioClient = new MinioClient(Configuration["MinIO:Endpoint"]
        , Configuration["MinIO:AccessKey"]
        , Configuration["MinIO:SecretKey"]);
    services.AddSingleton(minioClient);
    #endregion

    #region 带权限的swagger
    services.AddSwaggerGen(options =>
    {
        //定义api文档
        options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My API", Version = "v1" });
        //包含vs生成的注释文档
        //var xmlPath = Path.Combine(webHostEnvironment.ContentRootPath, Assembly.GetExecutingAssembly().GetName().Name + ".xml");
        //if (File.Exists(xmlPath))
        //{
        //    options.IncludeXmlComments(xmlPath, true);
        //}
        //描述安全信息
        options.AddSecurityDefinition(CookieAuthenticationDefaults.AuthenticationScheme, new OpenApiSecurityScheme()
        {
            Name = CookieAuthenticationDefaults.AuthenticationScheme,
            Scheme = CookieAuthenticationDefaults.AuthenticationScheme
        });
    });
    #endregion

    services.AddControllers();

    #region 不带权限的swagger
    //services.AddSwaggerGen(c =>
    //{
    //    c.SwaggerDoc("v1", new OpenApiInfo { Title = "MinioDemo.WebApi", Version = "v1" });
    //});
    #endregion


 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
    services.AddAuthorization();

}

appsetting,json

cs 复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  //minIO配置
  "MinIO": {
    //服务器IP
    "Endpoint": "localhost:9090",
    //账号
    "AccessKey": "minioadmin",
    //密码
    "SecretKey": "minioadmin",
    //默认存储桶
    "Bucket": "demo",
    //保存文件的根目录
    "BucketDirectory": "D:\\aaa\\bbb\\ccc"
  },
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://*:5000"
      }
    }
  },
  "PDM": {
    "Secret": "",
    "Uri": ""
  }
}

完整上传、下载代码

cs 复制代码
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System;
using Minio;
using System.Linq;
using Minio.Exceptions;
using Microsoft.AspNetCore.Authorization;
using Minio.DataModel;
using System.Reactive.Linq;
using System.Data;
using System.Reactive.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Newtonsoft.Json;

namespace MinIOTest.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    //[Authorize]
    public class MinIOController : ControllerBase
    {
        string _bucketName = string.Empty;//默认桶
        private readonly MinioClient _client;
        private readonly IConfiguration _configuration;

        public MinIOController(
            MinioClient client,
            IConfiguration configuration
            )
        {
            _client = client;
            _configuration = configuration;
            _bucketName = configuration["MinIO:Bucket"];
        }

        #region 测试
        [HttpGet]
        public async Task<dynamic> test()
        {
            return new { bb = "bbb", cc = "ccc" };
        }
        #endregion

        #region 上传文件
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="filePath">文件保存路径</param>
        /// <param name="files">文件</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<dynamic> UploadFile(string filePath, List<IFormFile> files)
        {
            long size = files.Sum(f => f.Length);
            try
            {
                bool isExists = await _client.BucketExistsAsync(_bucketName);//桶是否存在
                //如果桶不存在则创建桶
                if (!isExists)
                {
                    await _client.MakeBucketAsync(_bucketName);
                }
                foreach (var formFile in files)
                {
                    string saveFileName = $"{Path.GetFileName(formFile.FileName)}";//存储        的文件名
                    string objectName = $"/{filePath}/{saveFileName}";//文件保存路径
                    if (formFile.Length > 0)
                    {
                        Stream stream = formFile.OpenReadStream();
                        await _client.PutObjectAsync(_bucketName,
                            objectName,
                            stream,
                            formFile.Length,
                            formFile.ContentType);
                    }
                }
            }
            catch (MinioException ex)
            {
                _logger.LogError($"文件上传错误:{ex}");
                return Ok(new { Success = false, Message = $"文件上传错误:{ex.Message}"                                         });
            }
            return Ok(new { Success = true, Count = files.Count, Size = size });
        }
        #endregion 上传文件

        #region 下载文件
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName">文件地址</param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> DownloadFile(string fileName)
        {
            var memoryStream = new MemoryStream();

            try
            {
                await _client.StatObjectAsync(_bucketName, fileName);
                await _client.GetObjectAsync(_bucketName, fileName,
                                    (stream) =>
                                    {
                                        stream.CopyTo(memoryStream);
                                    });
                memoryStream.Position = 0;
            }
            catch (MinioException ex)
            {
                _logger.LogError($"下载附件发生错误:{ex}");
                return Ok(new { Success = false, Message = $"下载附件发生错误:{ex.Message}" });
            }

            return File(memoryStream, GetContentType(fileName));
        }
        #endregion 下载文件

        #region 获取文件ContentType类型
        private static string GetContentType(string fileName)
        {
            if (fileName.Contains(".jpg"))
            {
                return "image/jpg";
            }
            else if (fileName.Contains(".jpeg"))
            {
                return "image/jpeg";
            }
            else if (fileName.Contains(".png"))
            {
                return "image/png";
            }
            else if (fileName.Contains(".gif"))
            {
                return "image/gif";
            }
            else if (fileName.Contains(".pdf"))
            {
                return "application/pdf";
            }
            else if (fileName.Contains(".docx"))
            {
                return "application/msword";
            }
            else if (fileName.Contains(".txt"))
            {
                return "text/plain";
            }
            else
            {
                return "application/octet-stream";
            }
        }
        #endregion 获取文件类型

        #region 获取指定文件目录
        /// <summary>
        /// 获取指定文件目录
        /// </summary>
        /// <param name="prefixArr">文件路径(格式:["工程图纸/001","工程图纸/002"])        </param>
        /// <param name="fileName">文件名,模糊查询</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<object> GetFileListAsycn(string[] prefixArr, string fileName)
        {
            try
            {
                bool found = await _client.BucketExistsAsync(_bucketName);
                if (found)
                {
                    List<Item> filePathList = new List<Item>();
                    foreach (string prefix in prefixArr)
                    {
                        var files = _client.ListObjectsAsync(_bucketName, prefix, true);
                        var filePaths = files.ToList().Wait();
                        filePathList.InsertRange(filePathList.Count(), filePaths);
                    }
                    if (!string.IsNullOrEmpty(fileName))
                    {
                        filePathList = filePathList.Where(d =>         d.Key.Split('/').Last().Contains(fileName)).ToList();
                    }
                    return Ok(new { Success = true, Count = filePathList.Count(), Data = filePathList });
                }
                else
                {
                    return Ok(new { Success = false, Data = $"桶[{_bucketName}]不存在" });
                }
            }
            catch (MinioException ex)
            {
                _logger.LogError($"MinIO发生错误:{ex}");
                return Ok(new { Success = false, Data = $"MinIO发生错误:{ex.Message}" });
            }
        }
        #endregion 获取指定文件目录

        #region 获取最上层目录
        /// <summary>
        /// 获取最上层目录
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<object> GetDirectoryAsycn()
        {
            try
            {
                bool found = await _client.BucketExistsAsync(_bucketName);
                if (found)
                {
                    var files = _client.ListObjectsAsync(_bucketName, "", false);
                    var fileDirectory = files.ToList().Wait();
                    foreach (var file in fileDirectory)
                    {
                        file.Key = file.Key.Replace("/", "");
                    }
                    return Ok(new { Success = true, Data = fileDirectory });
                }
                else
                {
                    return Ok(new { Success = false, Data = $"桶[{_bucketName}]不存在" });
                }
            }
            catch (MinioException ex)
            {
                _logger.LogError($"MinIO发生错误:{ex}");
                return Ok(new { Success = false, Data = $"MinIO发生错误:{ex}" });
            }
        }
        #endregion 获取最上层目录  

    }
}

运行程序,如下图,上传接口

下载接口,输入文件地址

获取某个文件夹下的所有文件目录,递归获取

获取文件列表接口这里要要注意下,因为ListObjectsAsync这个接口是异步的,当自己写的接口执行完的时候,调用MinIO获取文件列表的接口还没执行完,所以,获取MinIO文件列表接口(ListObjectsAsync),要使用方法Wait()改成同步,即

cs 复制代码
var files = _client.ListObjectsAsync(_bucketName, prefix, true);
var filePaths = files.ToList().Wait();

这样,才能获取全部路径

获取根目录,非递归

其他api接口方法,查看官方文档,文档地址

Windows 的 MinIO 对象存储 --- MinIO Object Storage for Windows

.NET Client API参考文档 - MinIO 帮助文档 - 开发文档 - 文江博客

上一篇:MinIO (一)安装并生成windows服务

下一篇:

相关推荐
学不会•5 分钟前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜2 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic3 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā3 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年5 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder5 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
芋芋qwq5 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎