minio对象存储C++上传下载和流式传输-做项目必备存储方案
视频讲解及源码领取:minio对象存储C++上传下载和流式传输-做项目必备存储方案
1 MinIO 基础概念
1.1 核心概念
-
MinIO服务器: 高性能的对象存储服务器,兼容Amazon S3 API
-
存储桶(Bucket): 存储对象的容器,类似于文件夹
-
对象(Object): 存储在桶中的文件,可以是任意类型的数据
-
访问密钥: 用于身份验证的密钥对(Access Key + Secret Key)
1.2 系统架构

2 minio非docker单机快速部署
2.1 下载 MinIO 二进制文件
首先,你需要从 MinIO 官方 GitHub 发布页面下载最新版本的 MinIO 二进制文件。根据你的操作系统选择合适的版本。
对于 Linux 系统,你可以使用 wget 或者 curl 命令来下载 MinIO 的二进制文件。例如,在 Linux 上你可以这样操作:
wget https://dl.min.io/server/minio/release/linux-amd64/minio --no-check-certificate
如果你使用的是 macOS 或者 Windows,请访问 MinIO 官方发布页面找到适合你系统的版本并下载。
2.2 赋予执行权限
下载完成后,你需要为下载的 MinIO 二进制文件添加执行权限。在 Linux 或 macOS 上,你可以通过以下命令实现:
chmod +x mini
2.3 设置环境变量(可选)
为了增强安全性,建议设置 MINIO_ROOT_USER 和 MINIO_ROOT_PASSWORD 这两个环境变量来指定 MinIO 的 root 用户和密码。如果不设置,默认会生成随机凭证,这将使得登录变得困难。
在 Linux 或 macOS 中,你可以通过如下命令设置环境变量:
export MINIO_ROOT_USER='minioadmin'
export MINIO_ROOT_PASSWORD='minioadmin'
请确保替换 'minioadmin' 和 'minioadmin' 为你自己的用户名和密码。
2.4 启动 MinIO 服务器
现在,你可以通过运行以下命令启动 MinIO 服务器:
mkdir data
./minio server ./data
在这个命令中, /data 是你希望 MinIO 存储数据的目录路径。你可以根据需要更改这个路径。确保该目录存在并且有适当的读写权限。
启动后,你会看到类似如下的输出,其中包含了访问 MinIO 控制台的 URL、Access Key 和 Secret Key:
Endpoint: http://192.168.80.128:9000 http://127.0.0.1:9000
AccessKey: YOUR-ACCESSKEYHERE SecretKey: YOUR-SECRETKEYHERE
Browser Access:
http://192.168.80.128:9000 http://127.0.0.1:9000
完整打印:

2.5 访问 MinIO 控制台
打开浏览器,输入提供的 URL(通常是 http://<your-machine-ip>:9000 ,比如我现在是http://192.168. 80.128:9000),然后使用提供的 Access Key 和 Secret Key 登录 MinIO 控制台。

3 C++ SDK上传和下载文件
3.1 官方C++ sdk安装
需要依赖vcpkg
# 下载vcpkg
git clone https://github.com/microsoft/vcpkg.git
# 进入vcpkg
cd vcpkg
./bootstrap-vcpkg.sh
# 安装minio-cpp,时间有点久,耐心等待
./vcpkg install minio-cpp
3.2 编译范例
以cmake方式构建的范例工程
mkdir build && cd build
cmake ..
make
3.3 执行程序
3.3.1 minio_basic文件上传下载
# 将源码目录的test-file.txt拷贝到build目录
lqf@ubuntu:~/minio/app/build$ cp ../test-file.txt .
lqf@ubuntu:~/minio/app/build$ ./minio_basic
执行成功打印:
开始上传文件到MinIO...
文件上传成功, ETag:
存储位置: video/test-file.txt
=== 上传响应详细信息 ===
状态码: 0
ETag: d249d192f7ab36c408f21125c2bc44d0
版本ID: 无
请求ID: 无
主机ID: 无
开始从MinIO下载文件...
文件下载成功!
保存位置: ./downloaded-file.txt
程序执行完成!
下载的内容保存为downloaded-file.txt。
3.3.2 minio_stream文件流式上传
# 将源码目录的time.flv拷贝到build目录
lqf@ubuntu:~/minio/app/build$ cp ../time.flv .
lqf@ubuntu:~/minio/app/build$ ./minio_stream time.flv
执行成功打印:
=== 开始模拟web上传流式传输 ===
源文件: time.flv
目标位置: video/time.flv
每次读取: 32768 字节 (32KB)
文件总大小: 20184976 字节 (19711KB)
文件大于等于5MB,使用Multipart Upload...
Multipart Upload创建成功,Upload ID:
ZjU2YzkyMDMtN2VjOS00MDM4LTlkY2MtNzRhYTM3ZjA1MTlkLjgxNjEzZTk2LTc3MTUtNDc4MS04NWFjLWY0
ZWU5NjZhMTE4NngxNzUzODkyODQ4NjM1NTA0NTI1
从文件读取到内存: 32768 字节 (总计: 32768/20184976)
...........
从文件读取到内存: 32768 字节 (总计: 5242880/20184976)
从内存上传分块 1 到MinIO,大小: 5242880 字节
分块 1 上传成功,ETag: d871d94bf0052b021048d9bf49d09ce9
从文件读取到内存: 32768 字节 (总计: 5275648/20184976)
从文件读取到内存: 32768 字节 (总计: 5308416/20184976)
...........
从文
从文件读取到内存: 32768 字节 (总计: 10485760/20184976)
从内存上传分块 2 到MinIO,大小: 5242880 字节
分块 2 上传成功,ETag: f53d0a4fa53433a602045abafdd78fd3
从文件读取到内存: 32768 字节 (总计: 10518528/20184976)
从文件读取到内存: 32768 字节 (总计: 10551296/20184976)
...........
从文件读取到内存: 32768 字节 (总计: 15695872/20184976)
从文件读取到内存: 32768 字节 (总计: 15728640/20184976)
从内存上传分块 3 到MinIO,大小: 5242880 字节
分块 3 上传成功,ETag: bb624d69050b1e1eec98897d64aa6e5c
从文件读取到内存: 32768 字节 (总计: 15761408/20184976)
从文件读取到内存: 32768 字节 (总计: 15794176/20184976)
...........
从文件读取到内存: 32768 字节 (总计: 20119552/20184976)
从文件读取到内存: 32768 字节 (总计: 20152320/20184976)
从文件读取到内存: 32656 字节 (总计: 20184976/20184976)
从内存上传分块 4 到MinIO,大小: 4456336 字节
分块 4 上传成功,ETag: 0ee96f2a4d95d43db356889f57f50cbe
完成Multipart Upload...
=== 大文件上传完成 ===
文件上传成功!
总分块数: 4
最终ETag:
文件位置:
注意:文件已成功上传为完整文件。
这模拟了从文件读取32KB数据到内存,然后从内存上传到MinIO的场景。
=== 程序执行完成 ===
3.4 查看上传的文件

4 范例解析-minio_basic文件上传下载
本文档将详细介绍 minio_basic.cpp 文件中的代码实现,帮助开发者理解如何使用 MinIO C++ SDK 进行对象存储的基本操作,包括文件上传和下载。
4.1 程序流程分析
4.1.1 整体流程图

4.1.2 详细操作流程

4.2 代码详解
4.2.1 连接配置部分
// MinIO服务器连接配置
std::string minioEndpoint = "localhost:9000"; // 服务器地址
std::string accessKey = "minioadmin"; // 访问密钥
std::string secretKey = "minioadmin"; // 秘密密钥
bool useSSL = false; // 是否使用SSL
配置说明:
-
minioEndpoint : MinIO服务器的地址和端口
-
accessKey/secretKey : 用于身份验证的密钥对
-
useSSL : 控制是否使用HTTPS连接
4.2.2 客户端初始化

// MinIO服务器地址和端口
// 本地部署:localhost:9000
// 远程服务器:your-server-ip:9000
// 使用HTTPS:your-server-ip:9000
std::string minioEndpoint = "localhost:9000";
// 访问密钥ID (Access Key ID)
// 在MinIO控制台 -> Identity -> Users 中创建用户获取
// 默认管理员账号的Access Key是:minioadmin
std::string accessKey = "minioadmin";
// 秘密访问密钥 (Secret Access Key)
// 在MinIO控制台 -> Identity -> Users 中创建用户获取
// 默认管理员账号的Secret Key是:minioadmin
std::string secretKey = "minioadmin";
// 是否使用SSL/TLS加密连接
// true: 使用HTTPS (https://)
// false: 使用HTTP (http://)
bool useSSL = false;
// ==================== 创建MinIO客户端 ====================
// 初始化MinIO客户端对象,建立与服务器的连接
minio::s3::BaseUrl baseUrl(minioEndpoint, useSSL);
minio::creds::StaticProvider provider(accessKey, secretKey);
minio::s3::Client minio(baseUrl, &provider);
组件说明:
-
BaseUrl : 封装服务器地址和协议信息
-
StaticProvider : 提供静态的访问凭证
-
Client : MinIO操作的主要接口
4.2.3 文件上传实现
4.2.3.1 上传流程图

4.2.3.2 核心代码分析
// 1. 打开文件流
std::ifstream fileStream(filePath, std::ios::binary);
if (!fileStream.is_open()) {
std::cerr << "无法打开文件: " << filePath << std::endl;
return 1;
}
// 2. 获取文件大小
fileStream.seekg(0, std::ios::end);
long fileSize = fileStream.tellg();
fileStream.seekg(0, std::ios::beg);
// 3. 创建上传参数
minio::s3::PutObjectArgs args(fileStream, fileSize, 0);
args.bucket = bucketName;
args.object = objectName;
// 4. 执行上传
minio::s3::PutObjectResponse resp = minio.PutObject(args);
参数说明:
-
fileStream : 文件输入流,以二进制模式打开
-
fileSize : 文件大小,用于告知服务器预期数据量
-
args.bucket : 目标存储桶名称
-
args.object : 对象在存储桶中的名称
4.2.4 响应处理
if (!resp) {
std::cerr << "上传失败: " << resp.Error().String() << std::endl;
return 1;
}
// 获取响应信息
std::string etag = resp.headers.GetFront("etag");
std::cout << "状态码: " << resp.status_code << std::endl;
std::cout << "ETag: " << resp.etag << std::endl;
响应字段说明:
-
status_code : HTTP状态码
-
etag : 对象的唯一标识符
-
version_id : 对象版本ID(如果启用版本控制)
-
headers : 完整的HTTP响应头
4.2.5 文件下载实现
4.2.5.1 下载流程图

4.2.5.2 回调函数机制

// 设置数据回调函数
args.datafunc = [&outFile](minio::http::DataFunctionArgs dataArgs) -> bool {
outFile.write(dataArgs.datachunk.c_str(), dataArgs.datachunk.length());
return true;
};
回调函数说明:
-
采用Lambda表达式实现
-
dataArgs.datachunk : 接收到的数据块
-
返回 true 表示继续接收,返回 false 会中断下载
未完
更多推荐


所有评论(0)