# MinIO 存储服务 **Repository Path**: ruovea/minio-storage ## Basic Information - **Project Name**: MinIO 存储服务 - **Description**: 该项目实现了与 MinIO 对象存储服务的集成,提供了以下功能: 文件上传(支持多文件、流式上传) 文件下载(支持指定对象键、文件类型) 存储桶管理(创建、检查、删除) 预签名 URL 生成(用于上传和下载) 支持多种文件类型和内容类型映射 提供统一的返回结果封装类 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2026-05-07 - **Last Updated**: 2026-08-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MinIO 存储服务 MinIO 是一个高性能、兼容 S3 协议的对象存储服务,专为大规模数据基础设施而设计。本项目提供了一个基于 MinIO 的文件上传和下载服务接口,适用于 .NET 平台的应用程序。 ## 项目介绍 该项目实现了与 MinIO 对象存储服务的集成,提供了以下功能: - 文件上传(支持多文件、流式上传) - 文件下载(支持指定对象键、文件类型) - 存储桶管理(创建、检查、删除) - 预签名 URL 生成(用于上传和下载) - 支持多种文件类型和内容类型映射 - 提供统一的返回结果封装类 主要类和接口包括: - `IMinIOService`:定义了 MinIO 操作的核心接口 - `MinIOService`:MinIO 操作的具体实现类 - `StorageController`:提供 HTTP 接口供外部调用上传、下载等操作 - `MinioOptions`:MinIO 配置类,包含访问密钥、端点等信息 ## 软件架构 本项目基于 .NET Core 构建,采用 MVC 架构模式,主要模块包括: - **控制器层(Controllers)**:提供 RESTful API 接口,处理 HTTP 请求 - **服务层(Services)**:封装 MinIO 的具体操作逻辑 - **模型层(Models)**:定义数据传输对象(DTO)和返回结果封装类 - **配置层(Configuration)**:通过 `appsettings.json` 配置 MinIO 的连接信息 项目使用 `MinioClient` 与 MinIO 服务器进行交互,支持异步操作以提高性能。 ## 安装教程 1. **安装 MinIO 服务器** 下载并运行 MinIO 服务器: ```bash wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod +x minio ./minio server /data ``` 2. **配置 MinIO 访问信息** 修改 `appsettings.json` 文件,配置 MinIO 的访问信息: ```json { "MinioOptions": { "Endpoint": "http://localhost:9000", "AccessKey": "YOUR_ACCESS_KEY", "SecretKey": "YOUR_SECRET_KEY" } } ``` 3. **启动 .NET 应用程序** 使用 .NET CLI 启动项目: ```bash dotnet run ``` ## 使用说明 本仓库包含两个项目,配合使用: - **`MinioStorage`**:对外提供 RESTful API 的主服务(ASP.NET Core 6.0 Web API),通过 `StorageController` 暴露上传/下载接口。 - **`MinioTest`**:演示/测试用的 MVC 客户端,含 `HomeController` 上传/下载示例与 `MinioHelper` 工具类。 ### 一、服务端配置 MinIO 连接信息在 `MinioStorage/appsettings.json` 的 `Minio` 节点下配置(注意:是 `Minio` 而非 `MinioOptions`): ```json { "Minio": { "Endpoint": "127.0.0.1:9000", "Region": "127.0.0.1", "AccessKey": "minioadmin", "SecretKey": "minioadmin", "BucketName": "omsfile", "FileURL": "http://127.0.0.1:9000/file" } } ``` | 字段 | 说明 | | --- | --- | | `Endpoint` | MinIO 服务地址(IP:端口) | | `Region` | 区域标识 | | `AccessKey` / `SecretKey` | MinIO 访问密钥 | | `BucketName` | 默认存储桶名 | | `FileURL` | 文件访问 URL 前缀 | DI 注册位于 `Program.cs`,通过 `builder.Services.AddMinio(...)` 注入 `MinioClient`,并将 `IMinIOService` 注册为单例。开发环境下会自动启用 Swagger,访问 `http://localhost:/swagger` 即可在线调试接口。 ### 二、REST API 接口 #### 1. 上传文件 - **接口**:`POST /api/Storage/UploadFiles` - **Content-Type**:`application/json` - **请求体**(对应 `UploadFilesDto`): ```json { "ProjectCode": "project1", "BucketName": "bucket1", "Files": [ { "ObjectKey": "file1", "FileType": "jpg", "Base64": "" } ] } ``` 字段说明: | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `ProjectCode` | string | 是 | 项目编码,不能为空;会拼接到对象键前缀 | | `BucketName` | string | 否 | 存储桶名,为空时默认 `Defult`;不存在时自动创建并设置只读策略 | | `Files` | array | 是 | 文件列表,不能为空 | | `Files[].ObjectKey` | string | 是 | 文件标识(不含扩展名) | | `Files[].FileType` | string | 是 | 文件类型,必须为内置 `contentTypDict` 的键之一(见下方支持类型表) | | `Files[].Base64` | string | 是 | 文件内容的 Base64 字符串;`FileType=txt` 时按原始字符串编码,其余按 Base64 解码 | 最终存储的对象键为 `{ProjectCode}_{ObjectKey}.{FileType}`。 - **响应体**(`ServerResult`): ```json { "success": true, "message": "上传成功", "statusCode": 0, "data": ["project1_file1.jpg"] } ``` `data` 为上传成功后的对象 ID 数组,可直接用于下载接口的 `ObjectKey` 参数。 #### 2. 下载文件 - **接口**:`GET /api/Storage/{ProjectCode}/{BucketName}/{ObjectKey}?FileType=image` - **路径参数**: | 参数 | 说明 | | --- | --- | | `ProjectCode` | 项目编码(当前实现未参与查询,保留占位) | | `BucketName` | 存储桶名 | | `ObjectKey` | 对象键,需带扩展名,扩展名必须存在于 `contentTypDict` | - **查询参数**:`FileType`(可选,默认 `image`,当前实现未实际使用)。 - **响应**:以 `File` 结果返回二进制流,`Content-Type` 由对象扩展名映射得到。 - **示例**: ```bash GET /api/Storage/project1/bucket1/project1_file1.jpg ``` > 说明:当前实现依据 `ObjectKey` 的扩展名从内置字典推断 `Content-Type`,因此扩展名必须匹配支持类型表。 #### 3. 支持的文件类型 `contentTypDict` 内置支持的扩展名 / Content-Type 映射: | 扩展名 | ContentType | | --- | --- | | bmp | image/bmp | | jpg / jpeg / jpe | image/jpeg | | png | image/png | | gif | image/gif | | ico | image/x-ico | | tif / tiff | image/tiff | | fax | image/fax | | wbmp | image//vnd.wap.wbmp | | rp | image/vnd.rn-realpix | 不在表中的类型会在上传时抛出 `KeyNotFoundException`,或在下载时无法推断 `Content-Type`。 ### 三、统一返回结果 所有接口使用 `MinioStorage.Models.ServerResult` / `ServerResult` 封装: | 字段 | 类型 | 说明 | | --- | --- | --- | | `Success` | bool | 处理是否成功 | | `Message` | string | 提示消息(成功/失败原因/异常信息) | | `StatusCode` | int | 状态码(上传失败默认 401) | | `Data` | T | 返回数据,如上传后的对象 ID 数组 | ### 四、通过 `IMinIOService` 编程式调用 除 HTTP 接口外,可在代码中直接注入 `IMinIOService` 调用以下方法(实现位于 `IMinIOService.cs` 的 `MinIOService`): ```csharp public interface IMinIOService { // 表单文件上传(默认存入 omsfile 桶,自动创建桶并设置只读策略) Task> UploadAsync(FormFileCollection file); // 仅限图片上传(按扩展名/ContentType 校验) Task> UploadImageAsync(FormFileCollection file); // PDF 流式上传(对象名固定为 <桶名>-<时间戳>.pdf) Task> UploadPdf(Stream file); } ``` 返回的 `Result` 中 `Data.Url` 为文件访问地址。使用示例: ```csharp public class MyController : ControllerBase { private readonly IMinIOService _minio; public MyController(IMinIOService minio) => _minio = minio; [HttpPost("upload-img")] public async Task UploadImg(List files) { var result = await _minio.UploadImageAsync(new FormFileCollection(files)); return Ok(result); } } ``` > 注:`FileManagerController` 中已有上传图片的示例代码,但当前被整体注释,可按需放开并配合 `IMinIOService.UploadImageAsync` 使用。 ### 五、MinioTest 测试客户端 `MinioTest/minioClient` 是一个 ASP.NET Core MVC 项目,用于演示与 MinIO 的交互: - **`Views/Home/Index.cshtml`**:提供多文件上传表单,提交到 `Home/Upload`。 - **`HomeController.Upload`**:遍历表单文件,调用 `MinioHelper.BucketExists` 检查桶,再 `PutObjectAsync` 上传到 `blog` 桶的 `MinioUpload/` 前缀下(默认连接 `play.min.io` 公共服务,可按需切换到本地 `127.0.0.1:9000`)。 - **`HomeController.Download`**:根据文件名从 `products` 桶下载并返回 `FileStreamResult`,支持通过 `GetContentType_New` 推断 300+ 种扩展名的 ContentType。 - **`ExUtil/MinioHelper`**:封装了完整的 MinIO 操作工具类,可直接复用: | 分类 | 方法 | 说明 | | --- | --- | --- | | 存储桶 | `MakeBucket` / `ListBuckets` / `BucketExists` / `RemoveBucket` / `ListObjects` / `ListIncompleteUploads` | 桶的增删查、对象列举 | | 策略/通知 | `GetPolicy` / `SetPolicy` / `GetBucketNotification` / `SetBucketNotification` / `RemoveAllBucketNotifications` | 访问策略与事件通知 | | 对象 | `FGetObject` / `FPutObject` / `GetObjectAsync` / `PutObjectAsync` / `StatObject` / `CopyObject` / `RemoveObject` / `RemoveObjects` / `RemoveIncompleteUpload` | 对象上传、下载、拷贝、删除、元数据 | | 预签名 | `PresignedGetObject` / `PresignedPutObject` | 生成临时上传/下载 URL(默认 1000 秒,最大 7 天) | | 工具 | `Helper.DoContentType` / `Content_Type` 枚举 | 枚举到 ContentType 的映射 | `MinioHelper` 调用示例: ```csharp var minioClient = new MinioClient("127.0.0.1:9000", "minioadmin", "minioadmin"); // 创建桶 await MinioHelper.MakeBucket(minioClient, "my-bucket"); // 上传本地文件 await MinioHelper.FPutObject(minioClient, "my-bucket", "docs/readme.txt", @"D:\readme.txt"); // 下载到本地 await MinioHelper.FGetObject(minioClient, "my-bucket", "docs/readme.txt", @"D:\download\readme.txt"); // 生成 1 小时有效的预签名下载链接 var (ok, url) = await MinioHelper.PresignedGetObject(minioClient, "my-bucket", "docs/readme.txt", 3600); ``` ### 六、典型调用流程 1. 启动 MinIO 服务并记录 `Endpoint / AccessKey / SecretKey`。 2. 在 `MinioStorage/appsettings.json` 中填入连接信息。 3. `dotnet run` 启动 `MinioStorage` 服务,开发环境打开 `/swagger` 调试。 4. 客户端调用 `POST /api/Storage/UploadFiles` 上传,拿到 `data` 中的对象 ID。 5. 通过 `GET /api/Storage/{ProjectCode}/{BucketName}/{ObjectKey}` 下载或在前端直接访问。 6. 如需临时授权访问,可使用 `MinioHelper.PresignedGetObject` 生成预签名 URL。 ### 七、注意事项 - `StorageController.UploadFiles` 会自动创建不存在的桶,并为新桶设置匿名只读策略(`s3:GetObject` 对所有对象开放),上线前请确认是否符合安全要求。 - 上传时 `FileType` 必须命中内置 `contentTypDict`,否则会抛出异常;下载时 `ObjectKey` 扩展名同样需要命中该字典。 - `MinIOService` 中 `BucketName / FileURL / ContentRootPath` 为硬编码常量,迁移部署时需同步修改。 - `MinioTest` 默认连接公共 `play.min.io`,测试本地 MinIO 时请切换为 `127.0.0.1:9000` 并替换 AK/SK。 - 生产环境建议通过环境变量或密钥管理服务注入 `AccessKey/SecretKey`,不要将真实密钥提交到仓库。 ## 参与贡献 欢迎贡献代码和文档。请遵循以下步骤: 1. Fork 本仓库 2. 创建新分支(feature/your-feature-name) 3. 提交代码 4. 创建 Pull Request ## 开源许可 本项目采用 MIT 许可证。详见 `LICENSE` 文件。