multi_get_object_demo.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include <stdlib.h>
  2. #include <sys/stat.h>
  3. #include <iostream>
  4. #include <map>
  5. #include <string>
  6. #include <thread>
  7. #include <vector>
  8. #include "cos_api.h"
  9. #include "cos_sys_config.h"
  10. #include "util/auth_tool.h"
  11. /**
  12. * 本样例演示了如何使用 COS C++ SDK 进行对象的高级下载
  13. * 包括:多线程下载、断点下载(多线程、支持断点)、异步多线程下载、异步断点下载、异步简单下载
  14. * 均只支持下载到文件
  15. */
  16. using namespace qcloud_cos;
  17. uint64_t appid = 12500000000;
  18. std::string tmp_secret_id = "AKIDXXXXXXXX";
  19. std::string tmp_secret_key = "1A2Z3YYYYYYYYYY";
  20. std::string region = "ap-guangzhou";
  21. std::string bucket_name = "examplebucket-12500000000";
  22. std::string tmp_token = "token";
  23. /*
  24. * 本方法包含调用是否正常的判断,和请求结果的输出
  25. * 可通过本方法判断是否请求成功,并输出结果信息
  26. */
  27. void PrintResult(const qcloud_cos::CosResult& result, const qcloud_cos::BaseResp& resp) {
  28. if (result.IsSucc()) {
  29. std::cout << "Request Succ." << std::endl;
  30. std::cout << resp.DebugString() << std::endl;
  31. } else {
  32. std::cout << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
  33. std::cout << "HttpStatus=" << result.GetHttpStatus() << std::endl;
  34. std::cout << "ErrorCode=" << result.GetErrorCode() << std::endl;
  35. std::cout << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
  36. std::cout << "ResourceAddr=" << result.GetResourceAddr() << std::endl;
  37. std::cout << "XCosRequestId=" << result.GetXCosRequestId() << std::endl;
  38. std::cout << "XCosTraceId=" << result.GetXCosTraceId() << std::endl;
  39. }
  40. }
  41. /*
  42. * 通过参数形式初始化 CosAPI 对象
  43. */
  44. qcloud_cos::CosAPI InitCosAPI() {
  45. qcloud_cos::CosConfig config(appid, tmp_secret_id, tmp_secret_key, region);
  46. config.SetTmpToken(tmp_token); // 推荐使用临时密钥初始化 CosAPI 对象, 如果您使用永久密钥初始化 CosAPI 对象,请注释
  47. qcloud_cos::CosAPI cos_tmp(config);
  48. return cos_tmp;
  49. }
  50. /*
  51. * 该 Demo 示范如何使用多线程下载接口下载对象
  52. * 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象
  53. * 可通过全局设置下载线程池大小、range 大小。该线程池是每次上传独立的
  54. */
  55. void MultiGetObjectDemo(qcloud_cos::CosAPI& cos) {
  56. std::string file_path = "test_file/big_file.txt";
  57. std::string object_name = "big_file.txt";
  58. // 此配置是全局性配置,主动设置后,后续涉及多线程下载的接口,都使用此配置
  59. CosSysConfig::SetDownThreadPoolSize(10); // 下载线程池大小 默认10
  60. CosSysConfig::SetDownSliceSize(4 * 1024 * 1024); // 下载 range 大小 默认4M
  61. qcloud_cos::MultiGetObjectReq req(bucket_name, object_name, file_path);
  62. qcloud_cos::MultiGetObjectResp resp;
  63. qcloud_cos::CosResult result = cos.MultiGetObject(req, &resp);
  64. std::cout << "===================GetObjectResponse=====================" << std::endl;
  65. PrintResult(result, resp);
  66. std::cout << "=========================================================" << std::endl;
  67. }
  68. /*
  69. * 该 Demo 示范如何使用断点下载接口下载对象
  70. * 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象,支持断点下载
  71. * 可通过全局设置下载线程池大小、range 大小。该线程池是每次上传独立的。
  72. */
  73. void ResumableGetObjectDemo(qcloud_cos::CosAPI& cos) {
  74. std::string file_path = "test_file/big_file.txt";
  75. std::string object_name = "big_file.txt";
  76. qcloud_cos::GetObjectByFileReq req(bucket_name, object_name, file_path);
  77. qcloud_cos::GetObjectByFileResp resp;
  78. CosResult result = cos.ResumableGetObject(req, &resp);
  79. std::cout << "===================ResumableGetObject====================" << std::endl;
  80. PrintResult(result, resp);
  81. std::cout << "=========================================================" << std::endl;
  82. }
  83. /*
  84. * 该方法是异步下载对象的进度回调示例
  85. */
  86. void ProgressCallback(uint64_t transferred_size, uint64_t total_size, void* user_data) {
  87. qcloud_cos::ObjectReq* req = static_cast<qcloud_cos::ObjectReq*>(user_data);
  88. if (0 == transferred_size % 1048576) {
  89. std::cout << "ObjectName:" << req->GetObjectName() << ", TranferedSize:" << transferred_size << ",TotalSize:" << total_size << std::endl;
  90. }
  91. }
  92. /*
  93. * 该方法是异步下载对象的完成回调示例
  94. */
  95. void GetObjectAsyncDoneCallback(const SharedAsyncContext& context, void* user_data) {
  96. UNUSED_PARAM(user_data)
  97. std::cout << "MultiGetObjectAsyncDoneCallback, BucketName:"
  98. << context->GetBucketName()
  99. << ", ObjectName:" << context->GetObjectName()
  100. << ", LocalFile:" << context->GetLocalFilePath() << std::endl;
  101. // qcloud_cos::MultiGetObjectReq对应的响应为qcloud_cos::GetObjectByFileResp
  102. if (context->GetResult().IsSucc()) {
  103. // 获取响应
  104. std::cout << "AsyncMultiGetObject succeed" << std::endl;
  105. std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
  106. AsyncResp resp = context->GetAsyncResp();
  107. std::cout << "ETag:" << resp.GetEtag() << std::endl;
  108. std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
  109. } else {
  110. std::cout << "AsyncMultiGetObject failed" << std::endl;
  111. std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
  112. }
  113. }
  114. /*
  115. * 该 Demo 示范如何通过异步多线程接口下载对象
  116. * 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象
  117. * 可通过全局设置异步线程池大小、下载线程池大小、range 大小
  118. * 注意:异步线程池是全局共用的,供所有的异步调用使用。下载线程池、range 大小与所有多线程类型下载接口共用配置
  119. * 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度。而每个异步操作中,可能会调用多线程相关接口创建出供本次使用的下载线程池,从而并发下载对象。
  120. * 支持下载进度回调和下载状态回调
  121. */
  122. void AsyncMultiGetObjectDemo(qcloud_cos::CosAPI& cos) {
  123. CosSysConfig::SetAsynThreadPoolSize(2); // 设置异步线程池大小 默认2
  124. std::string local_file = "test_file/big_file.txt";
  125. std::string object_name = "big_file.txt";
  126. qcloud_cos::AsyncMultiGetObjectReq req(bucket_name, object_name, local_file);
  127. // 设置下载进度回调
  128. req.SetTransferProgressCallback(&ProgressCallback);
  129. // 设置下载状态回调
  130. req.SetDoneCallback(&GetObjectAsyncDoneCallback);
  131. // 设置私有数据,对应回调中的 user_data
  132. req.SetUserData(&req);
  133. // 开始下载
  134. SharedAsyncContext context = cos.AsyncMultiGetObject(req);
  135. std::cout << "===================AsyncMultiGetObject======================" << std::endl;
  136. // 等待下载结束
  137. std::cout << "wait finish..." << std::endl;
  138. context->WaitUntilFinish();
  139. // context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
  140. // 此时您的主线程如果立即结束,异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
  141. // 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
  142. // 检查结果
  143. if (context->GetResult().IsSucc()) {
  144. // 获取响应
  145. std::cout << "AsyncMultiGetObject succeed" << std::endl;
  146. std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
  147. AsyncResp resp = context->GetAsyncResp();
  148. std::cout << "ETag:" << resp.GetEtag() << std::endl;
  149. std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
  150. } else {
  151. std::cout << "AsyncMultiGetObject failed" << std::endl;
  152. std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
  153. }
  154. std::cout << "============================================================" << std::endl;
  155. }
  156. /*
  157. * 该 Demo 示范如何通过异步断点下载接口下载对象
  158. * 仅支持下载到文件,利用了分 range 多线程同时下载的方式下载对象,支持断点下载
  159. * 可通过全局设置异步线程池大小、下载线程池大小、range 大小。
  160. * 注意:异步线程池是全局共用的,供所有的异步调用使用。下载线程池、range 大小与所有多线程类型下载接口共用配置
  161. * 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度。而每个异步操作中,可能会调用多线程相关接口创建出供本次使用的下载线程池,从而并发下载对象。
  162. * 支持下载进度回调和下载状态回调
  163. */
  164. void AsyncResumableGetObjectDemo(qcloud_cos::CosAPI& cos) {
  165. std::string local_file = "test_file/big_file.txt";
  166. std::string object_name = "big_file.txt";
  167. qcloud_cos::AsyncGetObjectReq req(bucket_name, object_name, local_file);
  168. // 设置下载进度回调
  169. req.SetTransferProgressCallback(&ProgressCallback);
  170. // 设置下载状态回调
  171. req.SetDoneCallback(&GetObjectAsyncDoneCallback);
  172. // 设置私有数据,对应回调中的 user_data
  173. req.SetUserData(&req);
  174. // 开始下载
  175. SharedAsyncContext context = cos.AsyncResumableGetObject(req);
  176. std::cout << "===================AsyncResumableGetObject======================" << std::endl;
  177. // 等待下载结束
  178. std::cout << "wait finish..." << std::endl;
  179. context->WaitUntilFinish();
  180. // context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
  181. // 此时您的主线程如果立即结束,异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
  182. // 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
  183. // 检查结果
  184. if (context->GetResult().IsSucc()) {
  185. // 获取响应
  186. std::cout << "AsyncResumableGetObject succeed" << std::endl;
  187. std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
  188. AsyncResp resp = context->GetAsyncResp();
  189. std::cout << "ETag:" << resp.GetEtag() << std::endl;
  190. std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
  191. } else {
  192. std::cout << "AsyncResumableGetObject failed" << std::endl;
  193. std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
  194. }
  195. std::cout << "================================================================" << std::endl;
  196. }
  197. /*
  198. * 该 Demo 示范如何通过异步简单接口下载对象
  199. * 仅支持下载到文件
  200. * 可通过全局设置异步线程池大小
  201. * 注意:异步线程池是全局共用的,供异步调用使用
  202. * 例如调用两次异步接口,则两个异步操作会使用异步线程池进行调度
  203. * 支持下载进度回调和下载状态回调
  204. */
  205. void AsyncGetObjectDemo(qcloud_cos::CosAPI& cos) {
  206. std::string local_file = "test_file/text.txt";
  207. std::string object_name = "text.txt";
  208. qcloud_cos::AsyncGetObjectReq req(bucket_name, object_name, local_file);
  209. req.SetRecvTimeoutInms(1000 * 60);
  210. // 设置下载进度回调
  211. req.SetTransferProgressCallback(&ProgressCallback);
  212. // 设置下载状态回调
  213. req.SetDoneCallback(&GetObjectAsyncDoneCallback);
  214. // 设置私有数据,对应回调中的 user_data
  215. req.SetUserData(&req);
  216. // 开始下载
  217. SharedAsyncContext context = cos.AsyncGetObject(req);
  218. std::cout << "===================AsyncGetObject======================" << std::endl;
  219. // 等待下载结束
  220. std::cout << "wait finish..." << std::endl;
  221. context->WaitUntilFinish();
  222. // context->WaitUntilFinish()阻塞完毕的逻辑是:异步线程在下载时文件落盘完毕。
  223. // 此时您的主线程如果立即结束,异步线程可能正在进行资源释放、结束线程等过程。此时可能会产生crash。
  224. // 此问题并不会对文件的下载造成影响,仅仅是体验上可能会出现意料之外的崩溃信息。
  225. // 检查结果
  226. if (context->GetResult().IsSucc()) {
  227. // 获取响应
  228. std::cout << "AsyncGetObject succeed" << std::endl;
  229. std::cout << "Result:" << context->GetResult().DebugString() << std::endl;
  230. AsyncResp resp = context->GetAsyncResp();
  231. std::cout << "ETag:" << resp.GetEtag() << std::endl;
  232. std::cout << "Crc64:" << resp.GetXCosHashCrc64Ecma() << std::endl;
  233. } else {
  234. std::cout << "AsyncGetObject failed" << std::endl;
  235. std::cout << "ErrorMsg:" << context->GetResult().GetErrorMsg() << std::endl;
  236. }
  237. std::cout << "=======================================================" << std::endl;
  238. }
  239. int main() {
  240. qcloud_cos::CosAPI cos = InitCosAPI();
  241. CosSysConfig::SetLogLevel((LOG_LEVEL)COS_LOG_ERR);
  242. MultiGetObjectDemo(cos);
  243. ResumableGetObjectDemo(cos);
  244. AsyncMultiGetObjectDemo(cos);
  245. AsyncResumableGetObjectDemo(cos);
  246. AsyncGetObjectDemo(cos);
  247. }