Files
cos-cpp-sdk-v5/demo/object_op_demo/multi_get_object_demo.cpp
a158 3cf88acc07 BG
2026-04-05 20:22:11 +08:00

273 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdlib.h>
#include <sys/stat.h>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include <vector>
#include "cos_api.h"
#include "cos_sys_config.h"
#include "util/auth_tool.h"
/**
* 本样例演示了如何使用 COS C++ SDK 进行对象的高级下载
* 包括:多线程下载、断点下载(多线程、支持断点)、异步多线程下载、异步断点下载、异步简单下载
* 均只支持下载到文件
*/
using namespace qcloud_cos;
uint64_t appid = 12500000000;
std::string tmp_secret_id = "AKIDXXXXXXXX";
std::string tmp_secret_key = "1A2Z3YYYYYYYYYY";
std::string region = "ap-guangzhou";
std::string bucket_name = "examplebucket-12500000000";
std::string tmp_token = "token";
/*
* 本方法包含调用是否正常的判断,和请求结果的输出
* 可通过本方法判断是否请求成功,并输出结果信息
*/
void PrintResult(const qcloud_cos::CosResult& result, const qcloud_cos::BaseResp& resp) {
if (result.IsSucc()) {
std::cout << "Request Succ." << std::endl;
std::cout << resp.DebugString() << std::endl;
} else {
std::cout << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
std::cout << "HttpStatus=" << result.GetHttpStatus() << std::endl;
std::cout << "ErrorCode=" << result.GetErrorCode() << std::endl;
std::cout << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
std::cout << "ResourceAddr=" << result.GetResourceAddr() << std::endl;
std::cout << "XCosRequestId=" << result.GetXCosRequestId() << std::endl;
std::cout << "XCosTraceId=" << result.GetXCosTraceId() << std::endl;
}
}
/*
* 通过参数形式初始化 CosAPI 对象
*/
qcloud_cos::CosAPI InitCosAPI() {
qcloud_cos::CosConfig config(appid, tmp_secret_id, tmp_secret_key, region);
config.SetTmpToken(tmp_token); // 推荐使用临时密钥初始化 CosAPI 对象, 如果您使用永久密钥初始化 CosAPI 对象,请注释
qcloud_cos::CosAPI cos_tmp(config);
return cos_tmp;
}
/*
* 该 Demo 示范如何使用多线程下载接口下载对象
* 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象
* 可通过全局设置下载线程池大小、range 大小。该线程池是每次上传独立的
*/
void MultiGetObjectDemo(qcloud_cos::CosAPI& cos) {
std::string file_path = "test_file/big_file.txt";
std::string object_name = "big_file.txt";
// 此配置是全局性配置,主动设置后,后续涉及多线程下载的接口,都使用此配置
CosSysConfig::SetDownThreadPoolSize(10); // 下载线程池大小 默认10
CosSysConfig::SetDownSliceSize(4 * 1024 * 1024); // 下载 range 大小 默认4M
qcloud_cos::MultiGetObjectReq req(bucket_name, object_name, file_path);
qcloud_cos::MultiGetObjectResp resp;
qcloud_cos::CosResult result = cos.MultiGetObject(req, &resp);
std::cout << "===================GetObjectResponse=====================" << std::endl;
PrintResult(result, resp);
std::cout << "=========================================================" << std::endl;
}
/*
* 该 Demo 示范如何使用断点下载接口下载对象
* 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象,支持断点下载
* 可通过全局设置下载线程池大小、range 大小。该线程池是每次上传独立的。
*/
void ResumableGetObjectDemo(qcloud_cos::CosAPI& cos) {
std::string file_path = "test_file/big_file.txt";
std::string object_name = "big_file.txt";
qcloud_cos::GetObjectByFileReq req(bucket_name, object_name, file_path);
qcloud_cos::GetObjectByFileResp resp;
CosResult result = cos.ResumableGetObject(req, &resp);
std::cout << "===================ResumableGetObject====================" << std::endl;
PrintResult(result, resp);
std::cout << "=========================================================" << std::endl;
}
/*
* 该方法是异步下载对象的进度回调示例
*/
void ProgressCallback(uint64_t transferred_size, uint64_t total_size, void* user_data) {
qcloud_cos::ObjectReq* req = static_cast<qcloud_cos::ObjectReq*>(user_data);
if (0 == transferred_size % 1048576) {
std::cout << "ObjectName:" << req->GetObjectName() << ", TranferedSize:" << transferred_size << ",TotalSize:" << total_size << std::endl;
}
}
/*
* 该方法是异步下载对象的完成回调示例
*/
void GetObjectAsyncDoneCallback(const SharedAsyncContext& context, void* user_data) {
UNUSED_PARAM(user_data)
std::cout << "MultiGetObjectAsyncDoneCallback, BucketName:"
<< context->GetBucketName()
<< ", ObjectName:" << context->GetObjectName()
<< ", LocalFile:" << context->GetLocalFilePath() << std::endl;
// qcloud_cos::MultiGetObjectReq对应的响应为qcloud_cos::GetObjectByFileResp
if (context->GetResult().IsSucc()) {
// 获取响应
std::cout << "AsyncMultiGetObject succeed" << std::endl;
std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
AsyncResp resp = context->GetAsyncResp();
std::cout << "ETag:" << resp.GetEtag() << std::endl;
std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
} else {
std::cout << "AsyncMultiGetObject failed" << std::endl;
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
}
}
/*
* 该 Demo 示范如何通过异步多线程接口下载对象
* 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象
* 可通过全局设置异步线程池大小、下载线程池大小、range 大小
* 注意异步线程池是全局共用的供所有的异步调用使用。下载线程池、range 大小与所有多线程类型下载接口共用配置
* 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度。而每个异步操作中,可能会调用多线程相关接口创建出供本次使用的下载线程池,从而并发下载对象。
* 支持下载进度回调和下载状态回调
*/
void AsyncMultiGetObjectDemo(qcloud_cos::CosAPI& cos) {
CosSysConfig::SetAsynThreadPoolSize(2); // 设置异步线程池大小 默认2
std::string local_file = "test_file/big_file.txt";
std::string object_name = "big_file.txt";
qcloud_cos::AsyncMultiGetObjectReq req(bucket_name, object_name, local_file);
// 设置下载进度回调
req.SetTransferProgressCallback(&ProgressCallback);
// 设置下载状态回调
req.SetDoneCallback(&GetObjectAsyncDoneCallback);
// 设置私有数据,对应回调中的 user_data
req.SetUserData(&req);
// 开始下载
SharedAsyncContext context = cos.AsyncMultiGetObject(req);
std::cout << "===================AsyncMultiGetObject======================" << std::endl;
// 等待下载结束
std::cout << "wait finish..." << std::endl;
context->WaitUntilFinish();
// context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
// 此时您的主线程如果立即结束异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
// 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
// 检查结果
if (context->GetResult().IsSucc()) {
// 获取响应
std::cout << "AsyncMultiGetObject succeed" << std::endl;
std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
AsyncResp resp = context->GetAsyncResp();
std::cout << "ETag:" << resp.GetEtag() << std::endl;
std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
} else {
std::cout << "AsyncMultiGetObject failed" << std::endl;
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
}
std::cout << "============================================================" << std::endl;
}
/*
* 该 Demo 示范如何通过异步断点下载接口下载对象
* 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象,支持断点下载
* 可通过全局设置异步线程池大小、下载线程池大小、range 大小。
* 注意异步线程池是全局共用的供所有的异步调用使用。下载线程池、range 大小与所有多线程类型下载接口共用配置
* 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度。而每个异步操作中,可能会调用多线程相关接口创建出供本次使用的下载线程池,从而并发下载对象。
* 支持下载进度回调和下载状态回调
*/
void AsyncResumableGetObjectDemo(qcloud_cos::CosAPI& cos) {
std::string local_file = "test_file/big_file.txt";
std::string object_name = "big_file.txt";
qcloud_cos::AsyncGetObjectReq req(bucket_name, object_name, local_file);
// 设置下载进度回调
req.SetTransferProgressCallback(&ProgressCallback);
// 设置下载状态回调
req.SetDoneCallback(&GetObjectAsyncDoneCallback);
// 设置私有数据,对应回调中的 user_data
req.SetUserData(&req);
// 开始下载
SharedAsyncContext context = cos.AsyncResumableGetObject(req);
std::cout << "===================AsyncResumableGetObject======================" << std::endl;
// 等待下载结束
std::cout << "wait finish..." << std::endl;
context->WaitUntilFinish();
// context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
// 此时您的主线程如果立即结束异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
// 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
// 检查结果
if (context->GetResult().IsSucc()) {
// 获取响应
std::cout << "AsyncResumableGetObject succeed" << std::endl;
std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
AsyncResp resp = context->GetAsyncResp();
std::cout << "ETag:" << resp.GetEtag() << std::endl;
std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
} else {
std::cout << "AsyncResumableGetObject failed" << std::endl;
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
}
std::cout << "================================================================" << std::endl;
}
/*
* 该 Demo 示范如何通过异步简单接口下载对象
* 仅支持下载到文件
* 可通过全局设置异步线程池大小
* 注意:异步线程池是全局共用的,供异步调用使用
* 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度
* 支持下载进度回调和下载状态回调
*/
void AsyncGetObjectDemo(qcloud_cos::CosAPI& cos) {
std::string local_file = "test_file/text.txt";
std::string object_name = "text.txt";
qcloud_cos::AsyncGetObjectReq req(bucket_name, object_name, local_file);
req.SetRecvTimeoutInms(1000 * 60);
// 设置下载进度回调
req.SetTransferProgressCallback(&ProgressCallback);
// 设置下载状态回调
req.SetDoneCallback(&GetObjectAsyncDoneCallback);
// 设置私有数据,对应回调中的 user_data
req.SetUserData(&req);
// 开始下载
SharedAsyncContext context = cos.AsyncGetObject(req);
std::cout << "===================AsyncGetObject======================" << std::endl;
// 等待下载结束
std::cout << "wait finish..." << std::endl;
context->WaitUntilFinish();
// context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
// 此时您的主线程如果立即结束异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
// 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
// 检查结果
if (context->GetResult().IsSucc()) {
// 获取响应
std::cout << "AsyncGetObject succeed" << std::endl;
std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
AsyncResp resp = context->GetAsyncResp();
std::cout << "ETag:" << resp.GetEtag() << std::endl;
std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
} else {
std::cout << "AsyncGetObject failed" << std::endl;
std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
}
std::cout << "=======================================================" << std::endl;
}
int main() {
qcloud_cos::CosAPI cos = InitCosAPI();
CosSysConfig::SetLogLevel((LOG_LEVEL)COS_LOG_ERR);
MultiGetObjectDemo(cos);
ResumableGetObjectDemo(cos);
AsyncMultiGetObjectDemo(cos);
AsyncResumableGetObjectDemo(cos);
AsyncGetObjectDemo(cos);
}