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

news2025/1/18 9:11:26

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

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

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

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

创建桶

点击Buckets→Create Bucket创建桶

桶名可以命名为demo,点击确认

创建用户和秘钥

创建用户

创建AccessKey和SecretKey,点击Identity→Users→点击上一步创建的用户

把上面的AccessKey和SecretKey的值保存下来,可以在配置文件中使用。

创建WebApi项目

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

将Minio注入进来,并将minio连接信息配置在appsetting,json文件中Startup.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

"AccessKey"和"SecretKey"可以用账号密码,也可以用配置中,新加用户中的配置信息

{
  "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": ""
  }
}

完整上传、下载代码

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()改成同步,即

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服务

下一篇:MinIO (三) 使用Webhook实时同步文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

偏偏不信文心大模型4.0比肩GPT-4!我为它们安排了一场龙虎斗!

作者 | 卖萌酱 大家好&#xff0c;我是卖萌酱。盲猜点进本文的不少小伙伴也看了昨天的百度世界大会&#xff0c;百度创始人、董事长兼CEO李彦宏官宣文心大模型4.0发布&#xff0c;其中一句话让卖萌酱印象深刻&#xff1a;文心大模型4.0综合水平与GPT-4相比已经毫不逊色&#xf…

python二次开发Solidworks:画砂轮

先根据输入参数计算出绘制砂轮需要的数据&#xff0c;然后绘制草图&#xff0c;完全标注后生成旋转体&#xff0c;具体代码如下&#xff1a; import sympy as sy import numpy as np import matplotlib.pyplot as pltx1,y1为第一条直线端点坐标(-10,0),theta_l1为角度,取5*np.…

C语言实现用弦截法求 f(x)=x^3-5*x^2+16*x-80=0 的根

完整代码: //用弦截法求 func(x)x^3-5*x^216*x-800 的根 //弦截法就是用函数上两点&#xff0c;连线的斜率近似代替f(x) //公式为Xn1Xn−(Xn−Xn−1)*func(Xn)/(func(Xn)−f(Xn−1))#include<stdio.h> #include<math.h>//求f(x)的值 double func(double x){return…

博客后台模块

一、后台模块-准备工作 1. 前端工程启动 前端工程下载链接 https://pan.baidu.com/s/1TdFs4TqxlHh4DXyLwYuejQ 提取码&#xff1a;mfkw 项目sql文件下载链接 链接&#xff1a;https://pan.baidu.com/s/1DQCGN4wISSDlOkqnVWYwxA 提取码&#xff1a;mfkw 命令行进入keke-vu…

工业4.0时代数字化工厂的几个特点

随着工业4.0时代的到来&#xff0c;数字化工厂成为了制造业的重要组成部分。数字化工厂管理系统是一种应用数字化、自动化和物联网等技术与产业融合的全新生产方式&#xff0c;旨在提高生产效率、降低成本、提升产品质量&#xff0c;并增强企业的核心竞争力。 数字化工厂的核心…

用友GRP-U8 SQL注入漏洞复现

0x01 产品简介 用友GRP-U8R10行政事业财务管理软件是用友公司专注于国家电子政务事业&#xff0c;基于云计算技术所推出的新一代产品&#xff0c;是我国行政事业财务领域最专业的政府财务管理软件。 0x02 漏洞概述 用友GRP-U8的bx_historyDataCheck jsp、slbmbygr.jsp等接口存…

链上房产赛道项目 ESTATEX 研报:以 RWA 的方式释放房产市场的潜力

在上个世纪初&#xff0c;随着全球人口的指数型增长以及城市化趋势加速&#xff0c;全球房地产行业逐渐进入到发展的爆发期与红利期。一方面人口的暴增与城市化进程的的加速&#xff0c;让住宅和商业房地产逐渐形成了刚需&#xff0c;另一方面全球经济飞速发展&#xff0c;让越…

Leetcode.4 寻找两个正序数组的中位数

题目链接 Leetcode.4 寻找两个正序数组的中位数 hard 题目描述 给定两个大小分别为 m m m 和 n n n 的正序&#xff08;从小到大&#xff09;数组 n u m s 1 nums1 nums1 和 n u m s 2 nums2 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O…

Pinia学习-存储数据、修改数据以及持久化实现

Pinia是什么&#xff1f; Pinia 是 Vue 的存储库&#xff0c;实现全局变量的定义 这里定义的变量信息&#xff0c;任何页面都可以使用&#xff0c;代替原来的VueX 官网&#xff1a;https://pinia.web3doc.top/ 4.2 Pinia存储数据 4.2.1获取存储数据 实现步骤&#xff1a;…

比例夹管阀及其高精度压力和流量控制解决方案

摘要&#xff1a;针对卫生和无菌流体系统中柔性管路内的压力和流量控制&#xff0c;本文介绍了采用电控夹管阀的高精度控制解决方案。解决方案基于反馈控制原理&#xff0c;采用压力传感器或流量传感器进行测量并反馈给程序控制器&#xff0c;控制器驱动夹管阀来改变柔性管路的…

双目视觉实战--单视图测量方法

目录 一.简介 二、2D变换 1. 等距变换&#xff08;欧式变换&#xff09; 2. 相似变换 3. 仿射变换 4. 射影变换&#xff08;透视变换&#xff09; 5. 结论 三、影消点与影消线 1. 平面上的线 2. 直线的交点 3. 2D无穷远点 4. 无穷远直线 5. 无穷远点的透视变换与仿…

Yakit单兵作战神器简单使用

文章目录 免配置抓包破解编码数据包DNSLog 官网下载地址&#xff1a;https://yaklang.com/ 使用文档&#xff1a;https://www.yaklang.com/products/intro 免配置抓包 会启动一个和BurpSuite一样的内置浏览器 访问地址&#xff0c;就会拦截到数据包 也可以在history里查看 破解…

屏幕录制视频编辑软件 Camtasia 2023 mac中文版软件功能

Camtasia 2023 mac是一款功能强大的屏幕录制和视频编辑软件&#xff0c;可以用于制作教育课程、演示文稿、培训视频等。它具有一系列工具和功能&#xff0c;包括屏幕录制、视频编辑、音频编辑、字幕、特效等&#xff0c;使用户可以轻松地创建高质量的视频内容。 Camtasia2023的…

DH48WK 温控器参数设置

北京东昊力伟科技有限责任公司 温控仪、温度控制器 产品特点&#xff1a; 可外接温度传感器Pt100、Cu50、K、E、J、N、T、R、S、B兼容输入&#xff1b;PID控制输出、位式控制输出、继电器报警输出&#xff1b;控温能满足设定温度值的0.2℃&#xff1b;既可用于加热控制、也可…

VR数字政务为我们带来了哪些便捷之处?

每每在政务大厅排队的时候&#xff0c;总是在想未来政务服务会变成什么样子呢&#xff1f;会不会变得更加便捷呢&#xff1f;今天我们就来看看VR数字政务&#xff0c;能够为我们带来哪些便捷之处吧&#xff01; 传统的政务服务中&#xff0c;不仅办事流程复杂&#xff0c;而且每…

5.2 加载矢量图层(delimitedtext,spatialite,wfs,memory)

文章目录 前言加载矢量(vector)图层delimitedtextQGis导入CSV代码导入 SpatiaLite data provider (spatialite)QgsDataSourceUriQGis导入spatialite代码导入 Web服务WFS (web feature service) data provider (wfs)QGis添加图层代码添加 Memory data providerType (memory)QGis…

腾讯云服务器带宽下载速度快吗?多线BGP和CN2高速网络

腾讯云服务器公网带宽下载速度计算&#xff0c;1M公网带宽下载速度是128KB/秒&#xff0c;5M带宽下载速度是512KB/s&#xff0c;腾讯云10M带宽下载速度是1.25M/秒&#xff0c;腾讯云百科txybk.com来详细说下腾讯云服务器不同公网带宽实际下载速度以及对应的上传速度对照表&…

dig 简明教程

哈喽大家好&#xff0c;我是咸鱼 不知道大家在日常学习或者工作当中用 dig 命令多不多 dig 是 Domain Information Groper 的缩写&#xff0c;对于网络管理员和在域名系统(DNS)领域工作的小伙伴来说&#xff0c;它是一个非常常见且有用的工具。 无论是简单的 DNS 解析查找还…

第三章 数据结构与算法——栈和

栈和队列被称为插入和删除受限制的线性表。 &#x1f341;一、栈的基本概念 &#x1f315;&#xff08;一&#xff09;栈的概念&#xff1a; ①&#xff1a;栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈…

四川竹哲电子商务有限公司让抖音带货更轻松

随着电子商务的飞速发展&#xff0c;带货直播成为了新的行业热点。四川竹哲电子商务有限公司&#xff0c;一家在电子商务领域有着深厚实力和丰富经验的企业&#xff0c;正以其独特的视角和策略&#xff0c;引领着抖音带货的发展趋势&#xff0c;让这个新型商业模式更加轻松、高…