|
@@ -86,12 +86,28 @@ static int writeStringListCallback(void* buffer, size_t size, size_t nmemb, void
|
|
|
* @param pFile 文件指针
|
|
|
* @return size_t 实际读取的大小
|
|
|
*/
|
|
|
-static size_t writeDataCallBack(void* contents, size_t size, size_t nmemb, std::ostream* pFile)
|
|
|
+static size_t writeFileCallBack(void* contents, size_t size, size_t nmemb, std::ostream* pFile)
|
|
|
{
|
|
|
pFile->write(reinterpret_cast<char*>(contents), size * nmemb);
|
|
|
return size * nmemb;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @brief 写入数据到vector中
|
|
|
+ *
|
|
|
+ * @param contents
|
|
|
+ * @param size
|
|
|
+ * @param nmemb
|
|
|
+ * @param vecData
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+static size_t writeDataCallBack(void* contents, size_t size, size_t nmemb, std::vector<char>* vecData)
|
|
|
+{
|
|
|
+ size_t copySize = size * nmemb;
|
|
|
+ vecData->insert(vecData->end(), (char*)contents, (char*)contents + copySize);
|
|
|
+ return copySize;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief 读取文件回调函数
|
|
|
*
|
|
@@ -101,7 +117,7 @@ static size_t writeDataCallBack(void* contents, size_t size, size_t nmemb, std::
|
|
|
* @param pFile 文件指针
|
|
|
* @return size_t 写入的大小
|
|
|
*/
|
|
|
-static size_t readDataCallBack(void* contents, size_t size, size_t nmemb, std::istream* pFile)
|
|
|
+static size_t readFileCallBack(void* contents, size_t size, size_t nmemb, std::istream* pFile)
|
|
|
{
|
|
|
pFile->read(reinterpret_cast<char*>(contents), size * nmemb);
|
|
|
/* 获取读取到的字节数,可能读取到文件末尾,所以不能直接使用传入的字节数 */
|
|
@@ -111,6 +127,33 @@ static size_t readDataCallBack(void* contents, size_t size, size_t nmemb, std::i
|
|
|
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @brief
|
|
|
+ *
|
|
|
+ * @param contents ftp需要的目标内容
|
|
|
+ * @param size 拷贝的数据大小
|
|
|
+ * @param nmemb 单个数据的字节数
|
|
|
+ * @param pData 源指针
|
|
|
+ * @return size_t 已拷贝的数据大小
|
|
|
+ */
|
|
|
+static size_t readDataCallBack(void* contents, size_t size, size_t nmemb, CF_ArrayInfo* pData)
|
|
|
+{
|
|
|
+ if(pData == nullptr)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ /* 判断是否还够本次拷贝的字节数 */
|
|
|
+ size_t copySize = size * nmemb;
|
|
|
+ if(pData->size - pData->pos < copySize)
|
|
|
+ {
|
|
|
+ copySize = pData->size - pData->pos;
|
|
|
+ }
|
|
|
+ memcpy(contents, pData->data + pData->pos, copySize);
|
|
|
+ pData->pos += copySize;
|
|
|
+
|
|
|
+ return copySize;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief 计算速度
|
|
|
*
|
|
@@ -378,150 +421,15 @@ CurlFtp::~CurlFtp()
|
|
|
}
|
|
|
|
|
|
|
|
|
-/**
|
|
|
- * @brief 列出FTP文件夹
|
|
|
- *
|
|
|
- * @param ftpUrl 需要列出文件夹的FTP地址
|
|
|
- * @param username
|
|
|
- * @param password
|
|
|
- * @return std::string
|
|
|
- */
|
|
|
-// std::string CurlFtp::listDir(const std::string &ftpUrl, const std::string &username, const std::string &password)
|
|
|
-// {
|
|
|
-// CURL *curl;
|
|
|
-// CURLcode res;
|
|
|
-// bool result = false;
|
|
|
-// std::string retList;
|
|
|
-// /* 1. 初始化curl,这个函数需要在调用任何curl函数之前 */
|
|
|
-// curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
|
-// /* 2. 获取一个curl句柄 */
|
|
|
-// curl = curl_easy_init();
|
|
|
-// if(curl)
|
|
|
-// {
|
|
|
-// /* 3. 设置curl选项 */
|
|
|
-// curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
|
|
|
-// // curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L); // We only want the directory listing
|
|
|
-
|
|
|
-// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringCallback);
|
|
|
-// curl_easy_setopt(curl, CURLOPT_WRITEDATA, &retList);
|
|
|
-
|
|
|
-// /* 4. 发送信息,一直等待知道返回 */
|
|
|
-// res = curl_easy_perform(curl);
|
|
|
-// // printf("res = %d\n", res);
|
|
|
-// if(res != CURLE_OK)
|
|
|
-// {
|
|
|
-// fprintf(stderr, "getDirList() failed, error code %d, :%s\n",res, curl_easy_strerror(res));
|
|
|
-// } else
|
|
|
-// {
|
|
|
-// // std::cout << "Directory list: \n" << retList << std::endl;
|
|
|
-// }
|
|
|
-// /* 5. 清理curl */
|
|
|
-// curl_easy_cleanup(curl);
|
|
|
-// }
|
|
|
-// if(hasInstace == false)
|
|
|
-// {
|
|
|
-// curl_global_cleanup();
|
|
|
-// }
|
|
|
-// return retList;
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-/* 列出文件夹中的所有文件 */
|
|
|
-// bool CurlFtp::listFiles(const std::string &ftpUrl, const std::string &username, const std::string &password, std::vector<std::string>& fileList)
|
|
|
-// {
|
|
|
-// CURL *curl;
|
|
|
-// CURLcode res;
|
|
|
-// bool result = false;
|
|
|
-
|
|
|
-// curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
|
-// curl = curl_easy_init();
|
|
|
-// if(curl)
|
|
|
-// {
|
|
|
-// curl_easy_setopt(curl, CURLOPT_URL, (ftpUrl).c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);
|
|
|
-// curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeStringListCallback);
|
|
|
-// curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fileList);
|
|
|
-
|
|
|
-// res = curl_easy_perform(curl);
|
|
|
-// if(res != CURLE_OK)
|
|
|
-// {
|
|
|
-// fprintf(stderr, "Failed to get file list, error code :%d ,%s\n", res, curl_easy_strerror(res));
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// // for(const std::string& filename : fileList)
|
|
|
-// // {
|
|
|
-// // printf("%s\n", filename.c_str());
|
|
|
-// // }
|
|
|
-// result = true;
|
|
|
-// }
|
|
|
-
|
|
|
-// curl_easy_cleanup(curl);
|
|
|
-// }
|
|
|
-
|
|
|
-// if(hasInstace == false)
|
|
|
-// {
|
|
|
-// curl_global_cleanup();
|
|
|
-// }
|
|
|
-// return result;
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-/* 创建文件夹 */
|
|
|
-// bool CurlFtp::createDir(const std::string &ftpUrl, const std::string &username, const std::string &password, const std::string &dirName)
|
|
|
-// {
|
|
|
-// CURL *curl;
|
|
|
-// CURLcode res;
|
|
|
-// bool result = false;
|
|
|
-
|
|
|
-// curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
|
-// curl = curl_easy_init();
|
|
|
-// if(curl)
|
|
|
-// {
|
|
|
-// curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
|
|
|
-// curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
|
|
|
-
|
|
|
-// // Create a list of FTP commands to be executed on the server
|
|
|
-// struct curl_slist *headerlist = NULL;
|
|
|
-// std::string mkdir = "MKD " + dirName;
|
|
|
-// headerlist = curl_slist_append(headerlist, mkdir.c_str());
|
|
|
-
|
|
|
-// // Set the list of FTP commands to be executed on the server before the transfer
|
|
|
-// curl_easy_setopt(curl, CURLOPT_QUOTE, headerlist);
|
|
|
-// // Tell libcurl to not include the body in the output
|
|
|
-// curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
|
|
-
|
|
|
-// res = curl_easy_perform(curl);
|
|
|
-
|
|
|
-// if(res != CURLE_OK)
|
|
|
-// {
|
|
|
-// fprintf(stderr, "createDir() failed, error code :%d ,%s\n", res, curl_easy_strerror(res));
|
|
|
-// result = false;
|
|
|
-// }else
|
|
|
-// {
|
|
|
-// result = true;
|
|
|
-// }
|
|
|
-
|
|
|
-// curl_easy_cleanup(curl);
|
|
|
-// curl_slist_free_all(headerlist);
|
|
|
-// }
|
|
|
-
|
|
|
-// if(hasInstace == false)
|
|
|
-// {
|
|
|
-// curl_global_cleanup();
|
|
|
-// }
|
|
|
-// return result;
|
|
|
-// }
|
|
|
|
|
|
+/* 设置用户名和密码 */
|
|
|
+bool CurlFtp::setUsernameAndPassword(const std::string& username, const std::string& password)
|
|
|
+{
|
|
|
+ m_username = username;
|
|
|
+ m_password = password;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
|
|
|
/* 设置IP和端口 */
|
|
|
bool CurlFtp::setFtpIPAndPort(const std::string& IP, const int port)
|
|
@@ -558,15 +466,10 @@ void CurlFtp::setCaCertFile(const std::string& caCertFile)
|
|
|
m_caCertFile = caCertFile;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-/* 设置用户名和密码 */
|
|
|
-bool CurlFtp::setUsernameAndPassword(const std::string& username, const std::string& password)
|
|
|
+/* 设置是否启用CURL的调试信息 */
|
|
|
+void CurlFtp::enableCurlDebug(bool isPrint)
|
|
|
{
|
|
|
- m_username = username;
|
|
|
- m_password = password;
|
|
|
-
|
|
|
- return true;
|
|
|
+ m_enableCurlDebug = isPrint;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -668,6 +571,18 @@ bool CurlFtp::isDirExist(const std::string& dir)
|
|
|
/* 获取文件夹是否存在,不需要接收文件 */
|
|
|
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
|
|
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 启用持久连接 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
+
|
|
|
CURLcode res = curl_easy_perform(curl);
|
|
|
bool result = true;
|
|
|
if(res != CURLE_OK)
|
|
@@ -675,6 +590,11 @@ bool CurlFtp::isDirExist(const std::string& dir)
|
|
|
// SPDLOG_ERROR("Failed to get file list, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
result = false;
|
|
|
}
|
|
|
+ // bool ret = performCurl(curl);
|
|
|
+ // if(!ret)
|
|
|
+ // {
|
|
|
+ // SPDLOG_ERROR("Failed to create FTP Dir");
|
|
|
+ // }
|
|
|
|
|
|
return result;
|
|
|
}
|
|
@@ -727,19 +647,27 @@ bool CurlFtp::createDirectory(const std::string& ftpDir)
|
|
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
|
|
|
|
|
|
- CURLcode res = curl_easy_perform(curl);
|
|
|
- bool result = true;
|
|
|
- if(res != CURLE_OK)
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+
|
|
|
+ if(m_enableCurlDebug)
|
|
|
{
|
|
|
- SPDLOG_ERROR("Failed to create FTP Dir, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
- result = false;
|
|
|
- }else
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+ // 启用持久连接
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
+
|
|
|
+ // CURLcode res = curl_easy_perform(curl);
|
|
|
+ bool ret = performCurl(curl);
|
|
|
+ if(!ret)
|
|
|
{
|
|
|
- result = true;
|
|
|
+ SPDLOG_ERROR("Failed to create FTP Dir");
|
|
|
}
|
|
|
+
|
|
|
curl_easy_cleanup(curl);
|
|
|
curl_slist_free_all(headerlist);
|
|
|
- return result;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/* 创建FTP文件夹,递归创建 */
|
|
@@ -786,8 +714,16 @@ bool CurlFtp::createDirectories(const std::string& ftpDir)
|
|
|
|
|
|
|
|
|
|
|
|
-/* 下载文件 */
|
|
|
-bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& localFile)
|
|
|
+/**
|
|
|
+ * @brief 下载文件
|
|
|
+ *
|
|
|
+ * @param remoteFile
|
|
|
+ * @param localFile
|
|
|
+ * @param timeout 超时时间,单位秒
|
|
|
+ * @return true
|
|
|
+ * @return false
|
|
|
+ */
|
|
|
+bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& localFile, size_t timeout)
|
|
|
{
|
|
|
if(m_ftpUrl.empty())
|
|
|
{
|
|
@@ -822,16 +758,17 @@ bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& loc
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
curl_easy_setopt(curl, CURLOPT_PORT, m_port);
|
|
|
/* 设置用户名和密码 */
|
|
|
- curl_easy_setopt(curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
- curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_USERPWD, (m_username + ":" + m_password).c_str());
|
|
|
/* 启用跟随重定向 */
|
|
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
/* 设置回调函数 */
|
|
|
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeDataCallBack);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFileCallBack);
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ofs);
|
|
|
/* 设置超时时间 */
|
|
|
// curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
|
|
/* 设置进度回调函数 */
|
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, nullptr);
|
|
@@ -853,7 +790,15 @@ bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& loc
|
|
|
curl_easy_setopt(curl, CURLOPT_CAINFO, m_caCertFile.c_str());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+ /* 启用持久连接 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
/* 发送请求 */
|
|
|
CURLcode res = curl_easy_perform(curl);
|
|
|
if(res != CURLE_OK)
|
|
@@ -876,15 +821,101 @@ bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& loc
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+/* 下载文件到数组 */
|
|
|
+bool CurlFtp::downloadToArray(const std::string& remoteFile, std::vector<char>& arrayInfo, size_t timeout)
|
|
|
+{
|
|
|
+ if(m_ftpUrl.empty())
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("ftpUrl is empty");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 检查传入的文件是否符合规范 */
|
|
|
+ std::string remoteFileTmp = checkFilePath(remoteFile);
|
|
|
+ std::string ftpUrl = m_ftpUrl + remoteFileTmp;
|
|
|
+
|
|
|
+ CURL* curl = nullptr;
|
|
|
+ curl = curl_easy_init();
|
|
|
+ if(curl == nullptr)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("curl init failed !");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 设置FTP地址 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_PORT, m_port);
|
|
|
+ /* 设置用户名和密码 */
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_USERPWD, (m_username + ":" + m_password).c_str());
|
|
|
+ /* 启用跟随重定向 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
+ /* 设置回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeDataCallBack);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &arrayInfo);
|
|
|
+ /* 设置超时时间 */
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
|
|
+ /* 设置进度回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_XFERINFODATA, nullptr);
|
|
|
+ /* 启用下载进度回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
|
|
+ /* 判断是否是SFTP */
|
|
|
+ if(m_isSftp)
|
|
|
+ {
|
|
|
+ /* 判断是否需要设置CA证书 */
|
|
|
+ if(m_isIgnoreSSLCert)
|
|
|
+ {
|
|
|
+ /* 忽略证书验证 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
|
+ /* 忽略主机名验证 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
|
+ } else
|
|
|
+ {
|
|
|
+ /* 设置CA证书 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_CAINFO, m_caCertFile.c_str());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+ /* 启用持久连接 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
+ /* 发送请求 */
|
|
|
+ CURLcode res = curl_easy_perform(curl);
|
|
|
+ if(res != CURLE_OK)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("Failed to get file list, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
+ SPDLOG_ERROR("Url = {}", ftpUrl);
|
|
|
+ /* 清理下载失败的文件 */
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ /* 清理curl */
|
|
|
+ curl_easy_cleanup(curl);
|
|
|
+
|
|
|
+ /* 打印一个换行符 */
|
|
|
+ // printf("\n");
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief 上传文件
|
|
|
*
|
|
|
* @param localFile 本地文件
|
|
|
* @param remoteFile 远程文件
|
|
|
+ * @param timeout 超时时间,单位秒
|
|
|
* @return true
|
|
|
* @return false
|
|
|
*/
|
|
|
-bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remoteFile)
|
|
|
+bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remoteFile, size_t timeout, bool isCreateDir)
|
|
|
{
|
|
|
if(m_ftpUrl.empty())
|
|
|
{
|
|
@@ -903,12 +934,19 @@ bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remote
|
|
|
/* 检查远程FTP上的文件夹是否存在,不存在则创建 */
|
|
|
if(!isDirExist(remoteDirTmp))
|
|
|
{
|
|
|
- if(!createDirectories(remoteDirTmp))
|
|
|
+ if(isCreateDir)
|
|
|
{
|
|
|
- // SPDLOG_ERROR("Failed to create remote dir: {}", remoteFileTmp);
|
|
|
+ if(!createDirectories(remoteDirTmp))
|
|
|
+ {
|
|
|
+ // SPDLOG_ERROR("Failed to create remote dir: {}", remoteFileTmp);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ SPDLOG_ERROR("Remote dir is not exist: {}", remoteDirTmp);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
/* 拼接远程文件的url */
|
|
|
std::string ftpUrl = m_ftpUrl + remoteFileTmp;
|
|
|
|
|
@@ -947,18 +985,28 @@ bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remote
|
|
|
/* 启用上传 */
|
|
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
|
|
/* 设置回调函数 */
|
|
|
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, readDataCallBack);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, readFileCallBack);
|
|
|
curl_easy_setopt(curl, CURLOPT_READDATA, &ifs);
|
|
|
/* 设置上传文件的大小 */
|
|
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
|
|
|
/* 设置超时时间 */
|
|
|
// curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
|
|
/* 设置进度回调函数 */
|
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
|
|
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, nullptr);
|
|
|
/* 启用下载进度回调函数 */
|
|
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
|
|
+
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+ /* 启用持久连接 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
/* 发送请求 */
|
|
|
CURLcode res = curl_easy_perform(curl);
|
|
|
bool result = true;
|
|
@@ -978,6 +1026,110 @@ bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remote
|
|
|
}
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * @brief 上传文件,上传数据
|
|
|
+ * 注意:函数内不会拷贝数据,因此在上传完成前需要保证该指针的有效性,拷贝完成后也不会销毁源数据
|
|
|
+ * 默认超时时间是30秒,也无法设置
|
|
|
+ *
|
|
|
+ * @param srcData 数据指针
|
|
|
+ * @param size 数据大小
|
|
|
+ * @param remoteFile 远程文件名,包括地址
|
|
|
+ * @param timeout 超时时间,单位秒
|
|
|
+ * @return true
|
|
|
+ * @return false
|
|
|
+ */
|
|
|
+bool CurlFtp::uploadData(char* srcData, size_t size, const std::string& remoteFile, size_t timeout, bool isCreateDir)
|
|
|
+{
|
|
|
+ if(m_ftpUrl.empty())
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("Url is empty");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 初始化本地数据 */
|
|
|
+ CF_ArrayInfo arrayInfo;
|
|
|
+ arrayInfo.data = srcData;
|
|
|
+ arrayInfo.size = size;
|
|
|
+ arrayInfo.pos = 0;
|
|
|
+ /* 检查FTP文件名是否符合规范 */
|
|
|
+ std::string remoteFileTmp = checkFilePath(remoteFile);
|
|
|
+ std::string remoteDirTmp = remoteFileTmp.substr(0, remoteFileTmp.find_last_of("/"));
|
|
|
+ /* 检查远程FTP上的文件夹是否存在,不存在则创建 */
|
|
|
+ if(!isDirExist(remoteDirTmp))
|
|
|
+ {
|
|
|
+ if(isCreateDir)
|
|
|
+ {
|
|
|
+ if(!createDirectories(remoteDirTmp))
|
|
|
+ {
|
|
|
+ // SPDLOG_ERROR("Failed to create remote dir: {}", remoteFileTmp);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ SPDLOG_ERROR("Remote dir is not exist: {}", remoteDirTmp);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* 拼接远程文件的url */
|
|
|
+ std::string ftpUrl = m_ftpUrl + remoteFileTmp;
|
|
|
+ SPDLOG_DEBUG("Data size: {}", arrayInfo.size);
|
|
|
+
|
|
|
+ CURL* curl = nullptr;
|
|
|
+ curl = curl_easy_init();
|
|
|
+ if(curl == nullptr)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("curl init failed !");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ /* 设置FTP地址 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_PORT, m_port);
|
|
|
+ /* 设置用户名和密码 */
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_USERPWD, (m_username + ":" + m_password).c_str());
|
|
|
+ /* 启用跟随重定向 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
+ /* 启用上传 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
|
|
+ /* 设置回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, readDataCallBack);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_READDATA, &arrayInfo);
|
|
|
+ /* 设置上传文件的大小 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)arrayInfo.size);
|
|
|
+ /* 设置超时时间 */
|
|
|
+ // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
|
|
+ /* 设置进度回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_XFERINFODATA, nullptr);
|
|
|
+ /* 启用下载进度回调函数 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
|
|
+
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+ /* 启用持久连接 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
+ /* 发送请求 */
|
|
|
+ CURLcode res = curl_easy_perform(curl);
|
|
|
+ bool result = true;
|
|
|
+ if(res != CURLE_OK)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("Upload file failed, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
+ SPDLOG_ERROR("Url = {}", ftpUrl);
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+ /* 关闭文件,清理curl */
|
|
|
+ curl_easy_cleanup(curl);
|
|
|
+ /* 打印一个换行符 */
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
|
@@ -1023,6 +1175,13 @@ bool CurlFtp::listAll(CURL* curl, std::string dir, std::vector<CF_FileInfo>& fil
|
|
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
|
|
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
|
|
|
|
|
|
+ // 禁用被动模式(如果需要)
|
|
|
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ /* 启用调试信息 */
|
|
|
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
/* 发送请求 */
|
|
|
CURLcode res = curl_easy_perform(curl);
|
|
|
if(res != CURLE_OK)
|
|
@@ -1115,5 +1274,26 @@ bool CurlFtp::checkLocalDir(const std::string& localDir)
|
|
|
}
|
|
|
|
|
|
|
|
|
+/* 执行curl,添加重试机制 */
|
|
|
+bool CurlFtp::performCurl(CURL* curl)
|
|
|
+{
|
|
|
+ int retry = 3;
|
|
|
+ while(retry > 0)
|
|
|
+ {
|
|
|
+ CURLcode res = curl_easy_perform(curl);
|
|
|
+ if(res == CURLE_OK)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }else
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("Perform curl failed, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
+ SPDLOG_ERROR("Retry times: {}", 3 - retry);
|
|
|
+ retry--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|