Qt 腾讯云对象存储

腾讯云对象存储

公司需要把软件日志文件传到服务端
对于 Qt 开发者来说当然不会用它们的 SDK 了,用是不可能用的,又不是不会coding
2021-01-27 看的文档开始开发

开发资料

请求签名 :https://cloud.tencent.com/document/product/436/7778
公共请求头部:https://cloud.tencent.com/document/product/436/7778

上传文件

对,没错,上传文件用的叫 put object
上传文件到存储桶,对没错,这个名字很 OK
put object:https://cloud.tencent.com/document/product/436/7749
为了搞这个上传文件 api, 搞了一天半才测试成功,一直吐槽文档写的跟奥利给一样,气的不行,第一天下班我还提交了工单,腾讯云小姐姐还电话给我问我要错误返回的参数,后来我自己调通了。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210128134039339.png

putUrl(“1.txt”)
注意把里面的 xxxx 都换成你自己申请的参数

/** hmac-sha1
 * @brief HttpClientClass::hmacSha1
 * @param key    秘钥
 * @param baseString   消息
 * @param isBase64   是否返回base64
 * @return
 */
QByteArray HttpClientClass::hmacSha1(QByteArray key, QByteArray baseString,bool isBase64)
{
    int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard
    if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression
        key = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
    }
    QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char"6"
    QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char"/"
    // ascii characters 0x36 ("6") and 0x5c ("/") are selected because they have large
    // Hamming distance (http://en.wikipedia.org/wiki/Hamming_distance)
    for (int i = 0; i < key.length(); i++) {
        innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length
        outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length
    }
    // result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64
    QByteArray total = outerPadding;
    QByteArray part = innerPadding;
    part.append(baseString);
    total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1));
    QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1);
    if(isBase64){
        return hashed.toBase64();
    }
    return hashed;
}
bool HttpClientClass::putUrl(const QString & filePath)
{
    QFileInfo fileInfo(filePath);
    if(!fileInfo.exists()){
        SCWarning<<QString("Not found file: %1").arg(filePath);
        return false;
    }

    //put到腾讯云
    //(存储桶)Bucket:collection-xxxxxx
    //(区域)Region:ap-shanghai
    QString qiniuPostUrl = "https://collection-xxxxxx.cos.ap-shanghai.myqcloud.com";
    QString SecretId = "AKxxxxxxxxxxxxxxxxxxxxxxxxx";
    QString SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";

    QFile file (fileInfo.filePath());
    if(!file.open(QIODevice::ReadOnly)){
        SCWarning<<QString("Open file failed: %1:%2").arg(filePath).arg(file.errorString());
        return false;
    }
    QByteArray fileData = file.readAll();
    //使用md5值作为文件的唯一名,保证服务器上文件名唯一
    QString md5file = QString(QCryptographicHash::hash( fileData, QCryptographicHash::Md5).toHex());
    //腾讯云需要用的文件名md5 (注意这里的md5计算方式,这里也卡了很久)
    QString fileMd5 = QString(QCryptographicHash::hash( fileData, QCryptographicHash::Md5).toBase64());
    SCDebug<<"fileMd5Str:"<<fileMd5;
    file.close();

    QString ContentLength = QString::number(fileData.size());
    QString ContentType = "text/plain";//text/plan
    //调试时,这里可以改成固定名 QString ContentDisposition = fileInfo.fileName()
    QString ContentDisposition = QString(md5file+"_"+fileInfo.fileName());
    QNetworkRequest req;
    req.setRawHeader("Host","collection-xxxxxx.cos.ap-shanghai.myqcloud.com");
    req.setRawHeader("Content-Length",ContentLength.toLocal8Bit());
    req.setRawHeader("Content-Type", ContentType.toLocal8Bit());
    req.setRawHeader("Content-Disposition", ContentDisposition.toLocal8Bit());
    req.setRawHeader("Content-MD5", fileMd5.toLocal8Bit());
    SCDebug<<"ContentLength:"<<ContentLength;
    QUrl url(qiniuPostUrl+"/"+ContentDisposition);
    req.setUrl(url);
    //有效期
    QDateTime startDateTime = QDateTime::currentDateTime();
    QDateTime endDateTime = startDateTime.addSecs(3600);
    quint64 startTimeS =  startDateTime.toSecsSinceEpoch();
    quint64 endTimeS =  endDateTime.toSecsSinceEpoch();
    QString KeyTime = QString("%1;%2").arg(startTimeS).arg(endTimeS);
    //可以把日期改成,官方提供的测试工具日期一直,方便查看自己的参数哪里出错了
    //    KeyTime = "1611800323;1611807523";
    SCDebug<<"KeyTime:"<<KeyTime;
    QByteArray SignKey = hmacSha1(SecretKey.toLocal8Bit(),KeyTime.toLocal8Bit(),false).toHex();
    SCDebug<<"SignKey:"<<QString(SignKey);
    QByteArray UrlParamList = QByteArray(); 
    QByteArray HttpParameters =  QByteArray();
    QMap<QString,QString>headMap;
    for(int i=0; i<req.rawHeaderList().size(); ++i){
        auto key = req.rawHeaderList().at(i);
        headMap.insert( key.toLower(),QUrl::toPercentEncoding(req.rawHeader(key)));
    }
    QByteArray  HeaderList = QString(headMap.keys().join(";")).toLocal8Bit();
    SCDebug<<"HeaderList:"<<QString(HeaderList);
    QByteArray HttpHeaders;
    for(int i=0; i<headMap.keys().size(); ++i){
        auto key = headMap.keys().at(i);
        HttpHeaders.append(key);
        HttpHeaders.append('=');
        HttpHeaders.append(headMap.value(key));
        if(i != headMap.keys().size() -1)
            HttpHeaders.append("&");
    }

    SCDebug<<"HttpHeaders:"<<HttpHeaders.size()<<QString(HttpHeaders);
    QString HttpURI = QString(QString("/%1").arg(ContentDisposition));
    //HttpParameters 这里只能用+号拼接,因为urlEncoded字符中可能出现%3这样误拼接
    QByteArray HttpString = QString("put\n"+HttpURI+"\n"+QString(HttpParameters)+"\n"+QString(HttpHeaders)+"\n").toLocal8Bit();
    //.arg(HttpURI).arg(QString(HttpParameters)).arg(QString(HttpHeaders)).toLocal8Bit();
    SCDebug<<"HttpString:"<<QString(HttpString);
    QByteArray httpStringSha1 = QCryptographicHash::hash(HttpString, QCryptographicHash::Sha1).toHex();
    SCDebug<<"httpStringSha1:"<<QString(httpStringSha1);
    QByteArray StringToSign = QString("sha1\n"+KeyTime+"\n"+httpStringSha1+"\n").toLocal8Bit();
    SCDebug<<"StringToSign:"<<QString(StringToSign);
    QByteArray Signature = hmacSha1(SignKey,StringToSign,false).toHex();
    SCDebug<<"Signature:"<<QString(Signature);
    //这里只能用+号拼接,因为urlEncoded字符中可能出现%3这样误拼接
    QString authorization = QString("q-sign-algorithm=sha1"
                                    "&q-ak="+SecretId+
                                    "&q-sign-time="+KeyTime+
                                    "&q-key-time="+KeyTime+
                                    "&q-header-list="+QString(HeaderList)+
                                    "&q-url-param-list="+QString(UrlParamList)+
                                    "&q-signature=")+QString(Signature);
    //            .arg(SecretId).arg(KeyTime).arg(KeyTime)
    //            .arg(QString(HeaderList)).arg(QString(UrlParamList)).arg(QString(Signature));
    SCDebug<<"Authorization:"<<authorization;
    req.setRawHeader("Authorization", authorization.toLocal8Bit());
    //put
    _reply = _pManager->put(req,fileData);
    SCDebug<<"_repley:"<<_reply->url();

    connect(_reply,SIGNAL(finished()),this,SLOT(slotReplyFinished()));
    connect(_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(slotReplyError(QNetworkReply::NetworkError)));
    return true;
}

在线调用工具

依这个工具为主,填入参数,切换到 [在线调用] 点击发送请求,会提示返回成功,查看签名过程与程序中输出的是否一致
https://console.cloud.tencent.com/api/explorer?Product=cos&Version=2018-11-26&Action=PutObject&SignVersion=
在这里插入图片描述

上传文件MD5计算方式

做完发现腾讯云文档中有几处二义性的地方
在这里插入图片描述

QString  fileMd5 = QString(QCryptographicHash::hash( fileData, QCryptographicHash::Md5).toBase64());

七牛云对象存储

https://blog.csdn.net/u012020854/article/details/113335590

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Qt中使用腾讯云对象存储SDK,需要按照以下步骤进行操作: 1. 下载腾讯云对象存储SDK,并将其解压到您的项目文件夹中。 2. 在Qt Creator中打开您的项目,选择“项目”菜单,然后选择“添加外部库”。 3. 在“添加外部库”对话框中,选择“系统库”,然后单击“浏览”按钮,找到您解压的腾讯云对象存储SDK文件夹中的“libqcloudcosxml.so”库文件,并选择它。 4. 在“添加外部库”对话框中,单击“确定”按钮,然后重新编译您的项目。 5. 在您的Qt代码中,包含腾讯云对象存储SDK的头文件,并使用SDK提供的API进行操作。 例如,以下是使用腾讯云对象存储SDK上传文件的示例代码: ```cpp #include "QCloudCosXml/QCloudCosXml.h" #include "QCloudCosXml/QCloudCosXmlGlobalConfig.h" #include "QCloudCosXml/QCloudCosXmlService.h" #include "QCloudCore/QCloudCore.h" int main(int argc, char *argv[]) { // 初始化腾讯云对象存储SDK QCloud::InitAPI(); // 配置全局参数 QCloud::CosXml::QCloudGlobalConfig::Instance().SetRegion("ap-guangzhou"); QCloud::CosXml::QCloudGlobalConfig::Instance().SetSecretId("<your_secret_id>"); QCloud::CosXml::QCloudGlobalConfig::Instance().SetSecretKey("<your_secret_key>"); QCloud::CosXml::QCloudGlobalConfig::Instance().SetAppid("<your_appid>"); // 创建对象存储服务 QCloud::CosXml::QCloudCosXmlService cosService; // 上传文件 QCloud::CosXml::Transfer::QCloudCOSXMLUploadObjectRequest request("<your_bucket_name>", "<your_object_key>", "<your_local_file_path>"); auto outcome = cosService.UploadObject(request); // 处理上传结果 if (outcome.IsSuccess()) { qDebug() << "Upload successfully!"; } else { qDebug() << "Upload failed:" << outcome.GetError().GetMessage().c_str(); } // 释放腾讯云对象存储SDK QCloud::ShutdownAPI(); return 0; } ``` 在上面的示例代码中,我们首先初始化了腾讯云对象存储SDK,并配置了全局参数(包括地域、密钥等信息)。 然后,我们创建了一个对象存储服务,并使用其提供的上传文件API上传了一个本地文件到指定的存储桶中。 最后,我们释放了腾讯云对象存储SDK。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值