Window下基於QT+阿里OSS編寫一個客戶端

主要技術

1.QT訪問阿里OSS,C++接口
2.QT動態控件
3.表格中顯示控
4.動態顯示阿里文件下載進度
3.QT PRI項目管理思路

設計步驟:

1.基於MINGW編譯aliyun-oss-cpp-sdk,生成libalibabacloud-oss-cpp-sdk.a
參考:https://blog.csdn.net/pengrui18/article/details/106903464
2.新建QT項目及PRI子項目
略過
3.將libalibabacloud-oss-cpp-sdk.a及相關庫文件加入子項目
略過
4.編寫界面顯示
阿里雲鏈接部分(這部分代碼參考網上的,改了一個接口函數download_files_to_memory() ):

alibabacloud_handle.cpp

#include "alibabacloud_handle.h"
#include <unistd.h>
#include <string.h>
namespace ALIBABACLOUD_HANDLE{

alibabacloud_handle::alibabacloud_handle(const std::string &AccessKeyId,const std::string &AccessKeySecret,const std::string &Endpoint,const std::string &BucketName):AccessKeyId(AccessKeyId),AccessKeySecret(AccessKeySecret),Endpoint(Endpoint),BucketName(BucketName)
{

    InitializeSdk();

    /* 設置連接池數,默認爲16個 */
    conf.maxConnections = 20;

    /* 設置請求超時時間,超時沒有收到數據就關閉連接,默認爲10000ms */
    conf.requestTimeoutMs = 8000;

    /* 設置建立連接的超時時間,默認爲5000ms */
    conf.connectTimeoutMs = 8000;

    oss_client = new OssClient(Endpoint, AccessKeyId, AccessKeySecret, conf);
    if(oss_client == NULL){
        status = -1;
        return;
    }else{
		status = 1;
	}

    auto callback = std::bind(&alibabacloud_handle::ProgressCallback,this,
        std::placeholders::_1,
        std::placeholders::_2,
        std::placeholders::_3,
        std::placeholders::_4
    );
    progressCallback = {  callback , this };

}

alibabacloud_handle::~alibabacloud_handle(){
    ShutdownSdk();
}

bool alibabacloud_handle:: upload_files(const std::string &target_path, const std::string &local_path){

    std::shared_ptr<std::iostream> content = std::make_shared<std::fstream>(local_path.c_str(), std::ios::in|std::ios::binary);
    PutObjectRequest request(BucketName, target_path, content);

    request.setTransferProgress(progressCallback);
    auto outcome = oss_client->PutObject(request);

    if (!outcome.isSuccess()) {
        /* 異常處理 */
        std::cout << "PutObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return false;
    }
    return true;
}


bool alibabacloud_handle::query_directory(const std::string &target_directory, std::vector<file_detail_st> &details){
    std::string nextMarker = "";

	ListObjectsRequest request1(BucketName);
	auto outcome = oss_client->ListObjects(request1);
    do {
        /* 列舉文件 */
        ListObjectsRequest request(BucketName);
         /* 設置正斜線(/)爲文件夾的分隔符 */
        request.setDelimiter("/");
        request.setPrefix(target_directory);
        request.setMarker(nextMarker);
        outcome = oss_client->ListObjects(request);

        if (!outcome.isSuccess ()) {    
            /* 異常處理 */
            std::cout << "ListObjects fail" <<
            ",code:" << outcome.error().Code() <<
            ",message:" << outcome.error().Message() <<
            ",requestId:" << outcome.error().RequestId() << std::endl;
            return false;
        }  
        for (const auto& object : outcome.result().ObjectSummarys()) {
            file_detail_st detail;
//            std::cout << "object"<<
//            ",name:" << object.Key() <<
//            " ,size:" << object.Size() <<
//            " ,lastmodify time:" << object.LastModified() << std::endl;
            detail.name = object.Key();
            detail.size = std::to_string(object.Size());
            detail.date = object.LastModified();
            details.push_back(detail);
        }
        for (const auto& commonPrefix : outcome.result().CommonPrefixes()) {
            std::cout << "commonPrefix" << ",name:" << commonPrefix << std::endl;
        }
        nextMarker = outcome.result().NextMarker();
    } while (outcome.result().IsTruncated());


    return true;
}

bool alibabacloud_handle::download_files(const std::string &target_directory,const std::string &local_directory){

    DownloadObjectRequest request(BucketName, target_directory, local_directory);
    request.setTransferProgress(progressCallback);

    auto outcome = oss_client->ResumableDownloadObject(request);
  
    if (!outcome.isSuccess()) {
        /* 異常處理 */
        std::cout << "ResumableDownloadObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return false;
    }else{
        return true;
    }
    
}


void alibabacloud_handle::ProgressCallback(size_t increment, int64_t transfered, int64_t total, void* userData) const
{
    alibabacloud_handle *handle_ptr = (alibabacloud_handle *)userData;
    int i = (int)((transfered*1.0/total*1.0) *100);
//    printf("[%d%%][%c]\r", i , lable[i % 4]);
//    fflush(stdout);
    handle_ptr->download_percent = i;
}

bool alibabacloud_handle::download_files_to_memory(const std::string &target_directory,std::string &buf){
    std::string strcontent;
    GetObjectRequest request(BucketName, target_directory);

    request.setTransferProgress(progressCallback);

    auto outcome = oss_client->GetObject(request);
    if (outcome.isSuccess()) { 
        std::cout << "getObjectToBuffer" << " success, Content-Length:" << outcome.result().Metadata().ContentLength() << std::endl;
        //*(outcome.result().Content()) >> buf;

//        *(outcome.result().Content())->getline()
        getline(*(outcome.result().Content()), buf, '\0');
    }
    else {
        /*異常處理*/
        std::cout << "getObjectToBuffer fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return false;
    }
    return true;
}
}


alibabacloud_handle.h

#pragma once

#include <string>
#include <stdio.h>
#include <alibabacloud/oss/OssClient.h>
#include <memory>
#include <fstream>
#include <iostream>
using namespace AlibabaCloud::OSS;

namespace ALIBABACLOUD_HANDLE{

struct file_detail_st
{
    std::string name;
    std::string size;
    std::string date;
};

class alibabacloud_handle{
public:
    // desc: 構造函數用於初始化OSS賬號信息以及初始化sdk
	// param: 參數一/AccessKeyId 參數二/AccessKeySecret 參數三/Endpoint 參數四/BucketName 
	// return: NULL
    alibabacloud_handle(const std::string &,const std::string &,const std::string &,const std::string &);

    // desc: 關閉sdk
	// param: NULL 
	// return: NULL
    ~alibabacloud_handle();
    
    int get_download_percent() {return download_percent;}
    // desc: 上傳文件
	// param: 參數一/阿里雲上的路徑及要保存的文件名 參數二/本地路徑 
	// return: 成功返回true,失敗返回false
    bool upload_files(const std::string &,const std::string &);

    // desc: 查詢阿里雲某路徑下的文件列表
    // param: 參數一/阿里雲上的路徑 參數二/文件列表
	// return: 成功返回true,失敗返回false
    bool query_directory(const std::string &, std::vector<file_detail_st> &);

    // desc: 下載文件到本地路徑下
	// param: 參數一/阿里雲上的路徑及要保存的文件名 參數二/本地路徑
	// return: 成功返回true,失敗返回false
    bool download_files(const std::string &,const std::string &);

    // desc: 下載文件到內存中
	// param: 參數一/阿里雲上的路徑及要保存的文件名 參數二/保存數據的字符串
	// return: 成功返回true,失敗返回false
    bool download_files_to_memory(const std::string &,std::string &);

    // desc: 進度條顯示
	// param: transfered/已完成的大小 total/總大小 
	// return: NULL
    void ProgressCallback(size_t increment, int64_t transfered, int64_t total, void* userData) const;

public:
    int status;

private:
    //OSS 通過使用 AccessKeyId 和 AccessKeySecret 對稱加密的方法來驗證某個請求的發送者身份。AccessKeyId 用於標識用戶;AccessKeySecret 是用戶用於加密簽名字符串和 OSS 用來驗證簽名字符串的密鑰,必須保密。
    std::string AccessKeyId;
    std::string AccessKeySecret;
    std::string Endpoint;       //OSS對外服務的訪問域名
    std::string BucketName;     //存儲空間名
    ClientConfiguration conf;
    OssClient *oss_client;
    TransferProgress progressCallback;
    const char lable[5] = {'|','/','-','\\','\\'};

    //Download Percent
    int download_percent;
};
}

動態控件及tableWidget顯示控件:


void frmAptest::UpdateTableWidget(int type)
{
    if (ossdatas.size() > 31)
    {
        return ;
    }

    ui->tableWidget->clearContents();

//    ui->tableWidget->setRowCount(32);
//    ui->tableWidget->setColumnCount(7);

    osswidgets.clear();
    for (int index = 0; index < 32; index++)
    {
        OSSWidget widget;

        widget.label_num_ptr = new QLabel("test");
        widget.label_filename_ptr = new QLabel("test");
        widget.label_filesize_ptr = new QLabel("test");
        widget.label_filedate_ptr = new QLabel("test");

        widget.btn_download_ptr = new QPushButton("下載");
        widget.btn_download_ptr->setObjectName(QString("btn_download%1").arg(index));
        widget.progress_download_ptr =  new QProgressBar();
        if (type == 1)
        {
            widget.btn_download_ptr->setEnabled(true);
            widget.progress_download_ptr->setEnabled(true);
        } else {
            widget.btn_download_ptr->setEnabled(false);
            widget.progress_download_ptr->setEnabled(false);
        }


        widget.btn_handle_ptr = new QPushButton("接管分析");
        widget.btn_handle_ptr->setObjectName(QString("btn_handle_%1").arg(index));
        widget.progress_handle_ptr =  new QProgressBar();
        if (type == 1)
        {
            widget.btn_handle_ptr->setEnabled(false);
            widget.progress_handle_ptr->setEnabled(false);
        } else {
            widget.btn_handle_ptr->setEnabled(true);
            widget.progress_handle_ptr->setEnabled(true);
        }


        connect(widget.btn_download_ptr, SIGNAL(clicked()), this, SLOT(slot_btn_clicked()));
        connect(widget.btn_handle_ptr, SIGNAL(clicked()), this, SLOT(slot_btn_handle_clicked()));
        osswidgets.push_back(widget);
    }

    oss_mutex_.lock();
    for (int index=0; index < ossdatas.size(); index++)
    {
        osswidgets[index].label_num_ptr->setText(QString("%1").arg(ossdatas[index].seqnum));
        osswidgets[index].label_num_ptr->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        osswidgets[index].label_filename_ptr->setText(QString::fromStdString(ossdatas[index].filename));
        osswidgets[index].label_filename_ptr->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        osswidgets[index].label_filesize_ptr->setText(QString::fromStdString(ossdatas[index].filesize));
        osswidgets[index].label_filesize_ptr->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        osswidgets[index].label_filedate_ptr->setText(QString::fromStdString(ossdatas[index].filedate));
        osswidgets[index].label_filedate_ptr->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);

        if (ossdatas[index].download_status == 1)
        {
            osswidgets[index].progress_download_ptr->setValue(100);
        } else if (ossdatas[index].download_status == 2) {
            osswidgets[index].progress_download_ptr->setValue(0);
            osswidgets[index].progress_handle_ptr->setStyleSheet("QProgressBar::chunk { background-color: rgb(255, 0, 0) }");
        } else {
            osswidgets[index].progress_download_ptr->setValue(0);
        }

        if (ossdatas[index].handle_status)
        {
            osswidgets[index].progress_handle_ptr->setValue(100);
        } else {
            osswidgets[index].progress_handle_ptr->setValue(0);
        }
        ui->tableWidget->setCellWidget(index, 0, osswidgets[index].label_num_ptr);
        ui->tableWidget->setCellWidget(index, 1, osswidgets[index].label_filename_ptr);
        ui->tableWidget->setCellWidget(index, 2, osswidgets[index].label_filesize_ptr);
        ui->tableWidget->setCellWidget(index, 3, osswidgets[index].label_filedate_ptr);
        //btn_download center show
        QWidget *btn_download_widget_ptr = new QWidget;
        QHBoxLayout *layout = new QHBoxLayout;
        layout->setSpacing(0);
        layout->setMargin(0);
        layout->addWidget(osswidgets[index].btn_download_ptr);
        btn_download_widget_ptr->setLayout(layout);
        ui->tableWidget->setCellWidget(index, 4, btn_download_widget_ptr);
        ui->tableWidget->setCellWidget(index, 5, osswidgets[index].progress_download_ptr);
        // btn_analyse center view.
        QWidget *btn_analsye_widget_ptr = new QWidget;
        QHBoxLayout *layout_analyse = new QHBoxLayout;
        layout_analyse->setSpacing(0);
        layout_analyse->setMargin(0);
        layout_analyse->addWidget(osswidgets[index].btn_handle_ptr);
        btn_analsye_widget_ptr->setLayout(layout_analyse);
        ui->tableWidget->setCellWidget(index, 6, btn_analsye_widget_ptr);
        ui->tableWidget->setCellWidget(index, 7, osswidgets[index].progress_handle_ptr);

    }
    oss_mutex_.unlock();
}

進度條顯示下載百分比:

##########################下載開始,設置狀態###################################
    if ("btn_download0" == btn_ptr->objectName())
    {

//        QString path = QCoreApplication::applicationDirPath();

        std::string remote_directory = ossdatas[0].filename;
        std::string local_directory = pathname + "/temp/" + ossdatas[0].filename;
        std::size_t pos = ossdatas[0].filename.find("/", 0);//.find(vehicleid, 0);
        local_filename = path.toStdString() + "/" + ossdatas[0].filename.substr(pos + 1);

        ossdatas[0].is_downloading = 1;

        std::thread([this, local_filename, remote_directory]() {
            if (handle_ptr->download_files(remote_directory, local_filename))
            {
//                ossdatas[0].is_downloading = false;
                ossdatas[0].download_status = 1;
//                osswidgets[0].progress_download_ptr->setValue(100);
            } else {
//                ossdatas[0].is_downloading = false;
                ossdatas[0].download_status = 2;
//                osswidgets[0].progress_download_ptr->setValue(0);
            }
        }).detach();
    }
##########################顯示部分,定時器取進度數據並顯示狀態###################################
	void frmAptest::slot_timeout()
{
    int i = 0;
    for (i=0; i < ossdatas.size(); i++)
    {
        if (ossdatas[i].is_downloading == 1)
        {
            break;
        }

    }
    if (i < ossdatas.size())
    {
        if (ossdatas[i].download_status == 1)
        {
            osswidgets[i].progress_download_ptr->setValue(handle_ptr->get_download_percent());
            if (handle_ptr->get_download_percent() >= 100)
            {
                ossdatas[i].is_downloading = false;
            }
        } else if (ossdatas[i].download_status == 2) {
            ossdatas[i].is_downloading = false;
            ossdatas[i].download_status = 0;
            osswidgets[i].progress_download_ptr->setValue(100);
            osswidgets[i].progress_download_ptr->setStyleSheet("QProgressBar::chunk{background:red}");
        }
    }

    for (i=0; i < ossdatas.size(); i++)
    {
        if (ossdatas[i].is_handling)
        {
            //std::cout << i << " is_handling" << std::endl;
            break;
        }
    }

    if (i < ossdatas.size())
    {
        if (ossdatas[i].handle_status == 1)
        {
            osswidgets[i].progress_handle_ptr->setValue(handle_ptr->get_download_percent());
            if (handle_ptr->get_download_percent() >= 100)
            {
//                std::cout << i << " is_handling ok" << std::endl;
                ossdatas[i].is_handling = false;
            }
            ossdatas[i].handle_status = 0;
        } else if (ossdatas[i].handle_status == 2) {
            ossdatas[i].is_handling = false;
            ossdatas[i].handle_status = 0;
            osswidgets[i].progress_handle_ptr->setValue(100);
            osswidgets[i].progress_handle_ptr->setStyleSheet("QProgressBar::chunk{background:red}");
        }

    }
}

效果圖

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章