使用docker创建minio分布式存储服务器

拉取minio

docker pull minio/minio

创建minio容器

docker run -p 9000:9000 -p 9001:9001 --name minio -e "MINIO_ROOT_USER=hongyaohongyao" -e "MINIO_ROOT_PASSWORD=hongyaohongyao123" -v /d/cache/docker/minio/data:/data -d minio/minio server /data --console-address ":9001"

MINIO_ROOT_USER也对应后面MinioClient初始化参数中的accessKey
MINIO_ROOT_PASSWORD对应secretKey

/d/表示D盘,即D://,docker的语法。

配置aws-cpp-sdk-s3

详见我的另一篇博客

实现的功能

  • 直接上传文本内容
  • 直接下载文本内容
  • 上传opencv的图片

因为个人的项目只需要在内存中操作数据,所以暂不支持本地文件的上传下载,有需要可以自己实现,思路差不多。

s3_utils.hpp

里面还加了直接上传opencv图像的方法,如果不需要可以删掉。


#ifndef S3_UTILS_HPP
#define S3_UTILS_HPP

#include <string>
#include <opencv2/opencv.hpp>
#include <aws/s3/S3Client.h>
#include <aws/core/Aws.h>

namespace s3_utils {
    void initAwsAPI(bool shutdown = false);

    class MinioClient {
        std::shared_ptr<Aws::S3::S3Client> client_;
    public:
        MinioClient(const std::string &endpoint, const std::string &accessKey, const std::string &secretKey);

        ~MinioClient() {
            client_.reset();
        }

        bool
        upload(const cv::Mat &img, const std::string &bucketName,
               const std::string &objectKey, const std::vector<int> &vecCompression_params = {});

        bool upload(const std::string &contents, const std::string &bucketName,
                    const std::string &objectKey);

        std::string download(const std::string &bucketName, const std::string &objectKey);

        cv::Mat downloadImg(const std::string &bucketName, const std::string &objectKey);
    };
}

#endif //S3_UTILS_HPP

s3_utils.cpp

#include <common/ilogger.hpp> 提供的INFO方法,可以自己换成其他的logger

注意Aws::InitAPI和Aws::ShutdownAPI是全局的,影响的是整个程序,所以启动和关闭都在整个程序中都只需要一次。之前没理解以为是一个Aws::SDKOptions控制一个,init和shutdown了多次,结果程序就崩了🤡。

#include "common/s3_utils.hpp"

#include "aws\core\auth\AWSCredentialsProvider.h"

#include "aws\s3\model\PutObjectRequest.h"
#include "aws\s3\model\GetObjectRequest.h"
#include <common/ilogger.hpp>

#undef GetObject
#undef GetMessage


void s3_utils::initAwsAPI(bool shutdown) {
    static bool isInited = false;
    static Aws::SDKOptions options;
    if (not isInited && not shutdown) {
        Aws::InitAPI(options);
        isInited = true;
    } else if (isInited && shutdown) {
        Aws::ShutdownAPI(options);
        isInited = false;
    }
}

s3_utils::MinioClient::MinioClient(const std::string &endpoint, const std::string &accessKey,
                                        const std::string &secretKey) {
    initAwsAPI();
    Aws::Client::ClientConfiguration cfg;
    cfg.endpointOverride = endpoint;  // S3服务器地址和端口
    INFO("endpoint %s access_key %s secret_key %s", endpoint.c_str(), accessKey.c_str(), secretKey.c_str());
    cfg.scheme = Aws::Http::Scheme::HTTP;
    cfg.verifySSL = false;
    client_ = std::make_shared<Aws::S3::S3Client>(Aws::Auth::AWSCredentials(accessKey, secretKey), cfg,
                                                  Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false);
}

bool s3_utils::MinioClient::upload(const cv::Mat &img,
                                        const std::string &bucketName,
                                        const std::string &objectKey, const std::vector<int> &vecCompression_params) {
    std::vector<uchar> vec_Img;
    imencode(".jpg", img, vec_Img, vecCompression_params);
    Aws::S3::Model::PutObjectRequest putObjectRequest;
    putObjectRequest.WithBucket(bucketName).WithKey(objectKey);
    auto img_stream = Aws::MakeShared<Aws::StringStream>("PutObjectInputStream");
    img_stream->write((char *) vec_Img.data(), (long long) vec_Img.size());
    putObjectRequest.SetBody(img_stream);
    auto putObjectResult = client_->PutObject(putObjectRequest);
    if (not putObjectResult.IsSuccess()) {
        INFO(putObjectResult.GetError().GetMessage().c_str());
        return false;
    }
    return true;
}

bool s3_utils::MinioClient::upload(const std::string &contents, const std::string &bucketName,
                                        const std::string &objectKey) {
    Aws::S3::Model::PutObjectRequest putObjectRequest;
    putObjectRequest.WithBucket(bucketName).WithKey(objectKey);
    auto contents_stream = Aws::MakeShared<Aws::StringStream>("PutObjectInputStream", contents);
    putObjectRequest.SetBody(contents_stream);
    auto putObjectResult = client_->PutObject(putObjectRequest);
    if (not putObjectResult.IsSuccess()) {
        INFO(putObjectResult.GetError().GetMessage().c_str());
        return false;
    }
    return true;
}

std::string s3_utils::MinioClient::download(const std::string &bucketName, const std::string &objectKey) {
    INFO("bucket: %s dir: %s", bucketName.c_str(), objectKey.c_str());
    Aws::S3::Model::GetObjectRequest object_request;
    object_request.WithBucket(bucketName).WithKey(objectKey);
    auto get_object_outcome = client_->GetObject(object_request);
    if (get_object_outcome.IsSuccess()) {
        std::ostringstream tmp;
        tmp << get_object_outcome.GetResult().GetBody().rdbuf();
        return tmp.str();
    } else {
        INFO(get_object_outcome.GetError().GetMessage().c_str());
        return "";
    }
}

cv::Mat s3_utils::MinioClient::downloadImg(const std::string &bucketName, const std::string &objectKey) {
    INFO("downloading img bucket: %s dir: %s", bucketName.c_str(), objectKey.c_str());
    Aws::S3::Model::GetObjectRequest object_request;
    object_request.WithBucket(bucketName).WithKey(objectKey);
    auto get_object_outcome = client_->GetObject(object_request);
    if (get_object_outcome.IsSuccess()) {
        auto &body = get_object_outcome.GetResult().GetBody();
        std::vector<uchar> vec_img;
        vec_img.assign(Aws::IStreamBufIterator(body), Aws::IStreamBufIterator());
        cv::Mat result = cv::imdecode(vec_img, cv::IMREAD_COLOR);
        return result;
    } else {
        INFO(get_object_outcome.GetError().GetMessage().c_str());
        return {};
    }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐