CurlFtp.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. #include "CurlFtp.h"
  2. #include <iostream>
  3. #include <regex>
  4. #include <iosfwd>
  5. /* 是否有初始化实例,主要用于静态函数调用curl_global_cleanup()函数前判断,有实例就不调用 */
  6. static bool hasInstace = false;
  7. /* ==================================================================================
  8. * *********************************** 全局函数 *************************************
  9. * ================================================================================== */
  10. /**
  11. * @brief 写入回调函数
  12. *
  13. * @param contents curl的数据缓冲区
  14. * @param size 数据大小,单位是size_t
  15. * @param nmemb size_t的单位字节数
  16. * @param s 用户提供的字符串
  17. * @return size_t 总共获取到的数据大小,单位是字节
  18. */
  19. static size_t writeStringCallback(void *contents, size_t size, size_t nmemb, std::string *s)
  20. {
  21. size_t newLength = size*nmemb;
  22. size_t oldLength = s->size();
  23. try
  24. {
  25. s->resize(oldLength + newLength);
  26. }
  27. catch(std::bad_alloc &e)
  28. {
  29. //handle memory problem
  30. return 0;
  31. }
  32. std::copy((char*)contents,(char*)contents+newLength,s->begin()+oldLength);
  33. return size*nmemb;
  34. }
  35. /**
  36. * @brief 写入回调函数,listFiles需要调用
  37. *
  38. * @param buffer curl下载回来的数据
  39. * @param size 数据大小
  40. * @param nmemb 数据单位字节数
  41. * @param userp 用户传进来的容器
  42. * @return int 返回拷贝的字节数
  43. */
  44. static int writeStringListCallback(void* buffer, size_t size, size_t nmemb, void* userp)
  45. {
  46. std::vector<std::string>* fileList = static_cast<std::vector<std::string>*>(userp);
  47. std::string line(static_cast<char*>(buffer), size * nmemb);
  48. // printf("line = %s\n", line.c_str());
  49. fileList->push_back(line);
  50. return size * nmemb;
  51. }
  52. /* ==================================================================================
  53. * *********************************** 成员函数 *************************************
  54. * ================================================================================== */
  55. CurlFtp::CurlFtp()
  56. {
  57. /* 调用初始化函数,这个函数可以重复调用 */
  58. curl_global_init(CURL_GLOBAL_DEFAULT);
  59. /* 初始化curl */
  60. m_curl = curl_easy_init();
  61. hasInstace = true;
  62. }
  63. CurlFtp::~CurlFtp()
  64. {
  65. /* 清理curl */
  66. curl_easy_cleanup(m_curl);
  67. curl_global_cleanup();
  68. hasInstace = false;
  69. }
  70. /* 检查文件夹是否存在,不确定好不好用 */
  71. // bool CurlFtp::isDirExists(const std::string &ftpUrl, const std::string &username, const std::string &password)
  72. // {
  73. // CURL *curl;
  74. // CURLcode res;
  75. // bool result = false;
  76. // std::string retList;
  77. // curl_global_init(CURL_GLOBAL_DEFAULT);
  78. // curl = curl_easy_init();
  79. // if(curl)
  80. // {
  81. // curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
  82. // curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
  83. // curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
  84. // // curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L); // We only want the directory listing
  85. // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
  86. // curl_easy_setopt(curl, CURLOPT_WRITEDATA, &retList);
  87. // res = curl_easy_perform(curl);
  88. // // printf("res = %d\n", res);
  89. // if(res != CURLE_OK)
  90. // {
  91. // fprintf(stderr, "getDirList() failed, error code %d, :%s\n",res, curl_easy_strerror(res));
  92. // }
  93. // else
  94. // {
  95. // // std::cout << "Directory list: \n" << retList << std::endl;
  96. // }
  97. // curl_easy_cleanup(curl);
  98. // }
  99. // curl_global_cleanup();
  100. // return result;
  101. // }
  102. /* 使用正则表达式提取出文件夹 */
  103. // bool CurlFtp::extractDirectories(const std::string& responseString)
  104. // {
  105. // std::regex directoryRegex(R"(^d.*\s(\S+)$)");
  106. // std::smatch match;
  107. // std::istringstream retStream(responseString);
  108. // std::string line;
  109. // while (std::getline(retStream, line))
  110. // {
  111. // if (std::regex_match(line, match, directoryRegex))
  112. // {
  113. // std::cout << "Directory: " << match[1] << std::endl;
  114. // }
  115. // }
  116. // return true;
  117. // }
  118. /**
  119. * @brief 列出FTP文件夹
  120. *
  121. * @param ftpUrl 需要列出文件夹的FTP地址
  122. * @param username
  123. * @param password
  124. * @return std::string
  125. */
  126. std::string CurlFtp::listDir(const std::string &ftpUrl, const std::string &username, const std::string &password)
  127. {
  128. CURL *curl;
  129. CURLcode res;
  130. bool result = false;
  131. std::string retList;
  132. /* 1. 初始化curl,这个函数需要在调用任何curl函数之前 */
  133. curl_global_init(CURL_GLOBAL_DEFAULT);
  134. /* 2. 获取一个curl句柄 */
  135. curl = curl_easy_init();
  136. if(curl)
  137. {
  138. /* 3. 设置curl选项 */
  139. curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
  140. curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
  141. curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
  142. // curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L); // We only want the directory listing
  143. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringCallback);
  144. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &retList);
  145. /* 4. 发送信息,一直等待知道返回 */
  146. res = curl_easy_perform(curl);
  147. // printf("res = %d\n", res);
  148. if(res != CURLE_OK)
  149. {
  150. fprintf(stderr, "getDirList() failed, error code %d, :%s\n",res, curl_easy_strerror(res));
  151. } else
  152. {
  153. // std::cout << "Directory list: \n" << retList << std::endl;
  154. }
  155. /* 5. 清理curl */
  156. curl_easy_cleanup(curl);
  157. }
  158. if(hasInstace == false)
  159. {
  160. curl_global_cleanup();
  161. }
  162. return retList;
  163. }
  164. /* 列出文件夹中的所有文件 */
  165. bool CurlFtp::listFiles(const std::string &ftpUrl, const std::string &username, const std::string &password, std::vector<std::string>& fileList)
  166. {
  167. CURL *curl;
  168. CURLcode res;
  169. bool result = false;
  170. curl_global_init(CURL_GLOBAL_DEFAULT);
  171. curl = curl_easy_init();
  172. if(curl)
  173. {
  174. curl_easy_setopt(curl, CURLOPT_URL, (ftpUrl).c_str());
  175. curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
  176. curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
  177. curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);
  178. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringListCallback);
  179. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fileList);
  180. res = curl_easy_perform(curl);
  181. if(res != CURLE_OK)
  182. {
  183. fprintf(stderr, "Failed to get file list, error code :%d ,%s\n", res, curl_easy_strerror(res));
  184. }
  185. else
  186. {
  187. // for(const std::string& filename : fileList)
  188. // {
  189. // printf("%s\n", filename.c_str());
  190. // }
  191. result = true;
  192. }
  193. curl_easy_cleanup(curl);
  194. }
  195. if(hasInstace == false)
  196. {
  197. curl_global_cleanup();
  198. }
  199. return result;
  200. }
  201. /* 创建文件夹 */
  202. bool CurlFtp::createDir(const std::string &ftpUrl, const std::string &username, const std::string &password, const std::string &dirName)
  203. {
  204. CURL *curl;
  205. CURLcode res;
  206. bool result = false;
  207. curl_global_init(CURL_GLOBAL_DEFAULT);
  208. curl = curl_easy_init();
  209. if(curl)
  210. {
  211. curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
  212. curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
  213. curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
  214. // Create a list of FTP commands to be executed on the server
  215. struct curl_slist *headerlist = NULL;
  216. std::string mkdir = "MKD " + dirName;
  217. headerlist = curl_slist_append(headerlist, mkdir.c_str());
  218. // Set the list of FTP commands to be executed on the server before the transfer
  219. curl_easy_setopt(curl, CURLOPT_QUOTE, headerlist);
  220. // Tell libcurl to not include the body in the output
  221. curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
  222. res = curl_easy_perform(curl);
  223. if(res != CURLE_OK)
  224. {
  225. fprintf(stderr, "createDir() failed, error code :%d ,%s\n", res, curl_easy_strerror(res));
  226. result = false;
  227. }else
  228. {
  229. result = true;
  230. }
  231. curl_easy_cleanup(curl);
  232. curl_slist_free_all(headerlist);
  233. }
  234. if(hasInstace == false)
  235. {
  236. curl_global_cleanup();
  237. }
  238. return result;
  239. }
  240. /* 设置IP和端口 */
  241. bool CurlFtp::setFtpIPAndPort(const std::string& IP, const std::string& port)
  242. {
  243. /*先判断是否有ftp器前缀,通过正则表达式,取出IP地址和端口号,去掉前缀和后面的'/ */
  244. m_IP = IP;
  245. m_port = port;
  246. m_ftpUrl = "ftp://" + m_IP + ":" + m_port;
  247. printf("ftpUrl = %s\n", m_ftpUrl.c_str());
  248. return true;
  249. }
  250. /* 设置用户名和密码 */
  251. bool CurlFtp::setFtpUsernameAndPassword(const std::string& username, const std::string& password)
  252. {
  253. m_username = username;
  254. m_password = password;
  255. return true;
  256. }
  257. /* 列出文件列表 */
  258. bool CurlFtp::listAll(std::string dir, std::vector<std::string>& fileList)
  259. {
  260. if(m_IP.empty() || m_port.empty())
  261. {
  262. printf("IP or port is empty\n");
  263. return false;
  264. }
  265. if(m_curl == nullptr)
  266. {
  267. printf("m_curl is nullptr\n");
  268. return false;
  269. }
  270. bool result = false;
  271. /* 先设置FTP地址 */
  272. std::string ftpUrl = m_ftpUrl + dir;
  273. curl_easy_setopt(m_curl, CURLOPT_URL, ftpUrl.c_str());
  274. /* 设置用户名和密码 */
  275. curl_easy_setopt(m_curl, CURLOPT_USERNAME, m_username.c_str());
  276. curl_easy_setopt(m_curl, CURLOPT_PASSWORD, m_password.c_str());
  277. /* 设置列出文件命令,只列出文件名称,不携带信息 */
  278. // curl_easy_setopt(m_curl, CURLOPT_DIRLISTONLY, 1L);
  279. /* 设置回调函数 */
  280. curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeStringListCallback);
  281. /* 设置需要写入的容器 */
  282. curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &fileList);
  283. /* 发送请求 */
  284. m_res = curl_easy_perform(m_curl);
  285. if(m_res != CURLE_OK)
  286. {
  287. fprintf(stderr, "Failed to get file list, error code :%d ,%s\n", m_res, curl_easy_strerror(m_res));
  288. result = false;
  289. } else
  290. {
  291. result = true;
  292. }
  293. // curl_easy_cleanup(m_curl);
  294. return result;
  295. }