|
@@ -339,6 +339,20 @@ static char* GBToUTF8(const char* gb2312)
|
|
|
}
|
|
|
#endif /* _WIN32 */
|
|
|
|
|
|
+
|
|
|
+/* 正则表达式,匹配多个空格 */
|
|
|
+const std::regex parseRegSpace(R"(( )+)");
|
|
|
+/* 匹配以非空格开头的字符,空格隔开,中间任意字符,空格隔开,非空格组成的结尾
|
|
|
+ * (文件类型) ... (文件大小,$5) ... (文件名)
|
|
|
+ */
|
|
|
+const std::regex parseReg1(R"(^([^ ]+) (\d*) (\w*) (\w*) (\d*) (.*) ([^ ]+)$)");
|
|
|
+// SPDLOG_INFO("\n-------------------\n");
|
|
|
+/* 匹配换行符,分割每一行 */
|
|
|
+const std::regex parseReg2(R"(\n)");
|
|
|
+/* 匹配文件夹 */
|
|
|
+const std::regex parseReg3(R"(^d.*)");
|
|
|
+/* 匹配文件 */
|
|
|
+const std::regex parseReg4(R"(^-.*$)");
|
|
|
/**
|
|
|
* @brief 解析字符串文件信息,如果FTP服务器规定好个编码,不需要进行转换
|
|
|
*
|
|
@@ -357,44 +371,44 @@ static bool parseFileInfo(const std::string& strSrc, std::vector<CF_FileInfo>& f
|
|
|
#endif /* _WIN32 */
|
|
|
|
|
|
// SPDLOG_DEBUG("\n{}", str2);
|
|
|
- /* 正则表达式,匹配多个空格 */
|
|
|
- std::regex reg(R"(( )+)");
|
|
|
- /* 匹配以非空格开头的字符,空格隔开,中间任意字符,空格隔开,非空格组成的结尾
|
|
|
- * (文件类型) ... (文件大小,$5) ... (文件名)
|
|
|
- */
|
|
|
- std::regex reg1(R"(^([^ ]+) (\d*) (\w*) (\w*) (\d*) (.*) ([^ ]+)$)");
|
|
|
- // SPDLOG_INFO("\n-------------------\n");
|
|
|
- /* 匹配换行符,分割每一行 */
|
|
|
- std::regex reg2(R"(\n)");
|
|
|
- /* 匹配文件夹 */
|
|
|
- std::regex reg3(R"(^d.*)");
|
|
|
- /* 匹配文件 */
|
|
|
- std::regex reg4(R"(^-.*$)");
|
|
|
+ // /* 正则表达式,匹配多个空格 */
|
|
|
+ // std::regex regSpace(R"(( )+)");
|
|
|
+ // /* 匹配以非空格开头的字符,空格隔开,中间任意字符,空格隔开,非空格组成的结尾
|
|
|
+ // * (文件类型) ... (文件大小,$5) ... (文件名)
|
|
|
+ // */
|
|
|
+ // std::regex reg1(R"(^([^ ]+) (\d*) (\w*) (\w*) (\d*) (.*) ([^ ]+)$)");
|
|
|
+ // // SPDLOG_INFO("\n-------------------\n");
|
|
|
+ // /* 匹配换行符,分割每一行 */
|
|
|
+ // std::regex reg2(R"(\n)");
|
|
|
+ // /* 匹配文件夹 */
|
|
|
+ // std::regex reg3(R"(^d.*)");
|
|
|
+ // /* 匹配文件 */
|
|
|
+ // std::regex reg4(R"(^-.*$)");
|
|
|
|
|
|
/* -1 表示对正则表达式之前的子序列感兴趣
|
|
|
* 0 表示对正则表达式本身感兴趣,输出的就是换行符 */
|
|
|
- std::sregex_token_iterator it2(str2.begin(), str2.end(), reg2, -1);
|
|
|
+ std::sregex_token_iterator it2(str2.begin(), str2.end(), parseReg2, -1);
|
|
|
/* 这里取出每一行 */
|
|
|
for(; it2 != std::sregex_token_iterator(); ++it2)
|
|
|
{
|
|
|
/* 去掉多余的空格 */
|
|
|
- auto line = std::regex_replace(it2->str(), reg, " ");
|
|
|
+ auto line = std::regex_replace(it2->str(), parseRegSpace, " ");
|
|
|
// SPDLOG_INFO("{}", line);
|
|
|
CF_FileInfo fi;
|
|
|
/* 取出文件类型 */
|
|
|
- std::string strFileType = std::regex_replace(line, reg1, "$1");
|
|
|
- if(std::regex_match(strFileType, reg3))
|
|
|
+ std::string strFileType = std::regex_replace(line, parseReg1, "$1");
|
|
|
+ if(std::regex_match(strFileType, parseReg3))
|
|
|
{
|
|
|
fi.type = CF_FileType::DIR;
|
|
|
- }else if (std::regex_match(strFileType, reg4))
|
|
|
+ }else if (std::regex_match(strFileType, parseReg4))
|
|
|
{
|
|
|
fi.type = CF_FileType::FILE;
|
|
|
}
|
|
|
/* 取出文件大小 */
|
|
|
- std::string strFileSize = std::regex_replace(line, reg1, "$5");
|
|
|
+ std::string strFileSize = std::regex_replace(line, parseReg1, "$5");
|
|
|
fi.size = std::stoull(strFileSize);
|
|
|
/* 取出文件名 */
|
|
|
- std::string strFileName = std::regex_replace(line, reg1, "$7");
|
|
|
+ std::string strFileName = std::regex_replace(line, parseReg1, "$7");
|
|
|
fi.name = strFileName;
|
|
|
/* 加入队列 */
|
|
|
fileInfo.push_back(fi);
|
|
@@ -554,63 +568,34 @@ bool CurlFtp::getDirList(std::string dir, std::vector<std::string>& dirList)
|
|
|
}
|
|
|
|
|
|
|
|
|
-/* 判断文件夹是否存在 */
|
|
|
+/**
|
|
|
+ * @brief 判断文件夹是否存在,FTP和SFTP判断方式不同
|
|
|
+ * FTP使用curl检测判断,但是SFTP无论文件夹是否存在都会返回真,所以只能通过列出文件夹的方式判断
|
|
|
+ *
|
|
|
+ * @param dir
|
|
|
+ * @return true
|
|
|
+ * @return false
|
|
|
+ */
|
|
|
bool CurlFtp::isDirExist(const std::string& dir)
|
|
|
{
|
|
|
- SPDLOG_DEBUG("Check dir: {}", dir);
|
|
|
+ SPDLOG_DEBUG("Check remote dir: {}", dir);
|
|
|
if(m_ftpUrl.empty())
|
|
|
{
|
|
|
SPDLOG_ERROR("ftpUrl is empty");
|
|
|
return false;
|
|
|
}
|
|
|
- /* 检查传入的文件夹 */
|
|
|
- auto dirTmp = checkDirPath(dir);
|
|
|
-
|
|
|
- // CURL* curl = nullptr;
|
|
|
- resetCurl(m_curl);
|
|
|
- std::string ftpUrl = m_ftpUrl + dirTmp;
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
- /* 获取文件夹是否存在,不需要接收文件 */
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_HEADER, 1L);
|
|
|
-
|
|
|
- /* 设置SFTP */
|
|
|
- setSftp(m_curl);
|
|
|
- /* 启用调试信息 */
|
|
|
- if(m_enableCurlDebug)
|
|
|
- {
|
|
|
- curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1L);
|
|
|
- }
|
|
|
-
|
|
|
- /* 启用持久连接 */
|
|
|
- // curl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
- /* 这里只需要执行一次 */
|
|
|
- CURLcode res = curl_easy_perform(m_curl);
|
|
|
- bool result = true;
|
|
|
- if(res == CURLE_REMOTE_FILE_NOT_FOUND)
|
|
|
+ if(dir == "/")
|
|
|
{
|
|
|
- result = false;
|
|
|
- }
|
|
|
- else if(res != CURLE_OK)
|
|
|
- {
|
|
|
- // SPDLOG_ERROR("Check remote dir error, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
- result = false;
|
|
|
+ return true;
|
|
|
}
|
|
|
- else
|
|
|
+ bool result = false;
|
|
|
+ if(m_isSftp)
|
|
|
{
|
|
|
- /* sftp即使远程文件夹不存在也会返回OK,这里使用http进行检查 */
|
|
|
- // long response_code = -1;
|
|
|
- // res = curl_easy_getinfo(m_curl, CURLINFO_HTTP_CONNECTCODE, &response_code);
|
|
|
- // if((res == CURLE_OK) && (response_code == 0))
|
|
|
- // {
|
|
|
- // SPDLOG_ERROR("Remote directory not found: {}", dir);
|
|
|
- // result = false;
|
|
|
- // }
|
|
|
- // SPDLOG_DEBUG("response_code: {}", response_code);
|
|
|
+ result = checkSftpDirExist(dir);
|
|
|
+ }else {
|
|
|
+ result = checkFtpDirExist(dir);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -644,24 +629,20 @@ bool CurlFtp::createDirectory(const std::string& ftpDir)
|
|
|
// SPDLOG_ERROR("Create FTP DIR, curl init failed !");
|
|
|
// return false;
|
|
|
// }
|
|
|
- if(m_curl == nullptr)
|
|
|
- {
|
|
|
- m_curl = curl_easy_init();
|
|
|
- if(m_curl == nullptr)
|
|
|
- {
|
|
|
- SPDLOG_ERROR("curl init failed !");
|
|
|
- return false;
|
|
|
- }
|
|
|
- }else {
|
|
|
- curl_easy_reset(m_curl);
|
|
|
- }
|
|
|
+ resetCurl(m_curl);
|
|
|
|
|
|
curl_easy_setopt(m_curl, CURLOPT_URL, m_ftpUrl.c_str());
|
|
|
curl_easy_setopt(m_curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
curl_easy_setopt(m_curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
/* 创建FTP头信息 */
|
|
|
struct curl_slist *headerlist = NULL;
|
|
|
- std::string mkdir = "MKD " + dirTmp;
|
|
|
+ std::string mkdir;
|
|
|
+ if(m_isSftp)
|
|
|
+ {
|
|
|
+ mkdir = "MKDIR " + dirTmp;
|
|
|
+ }else {
|
|
|
+ mkdir = "MKD " + dirTmp;
|
|
|
+ }
|
|
|
headerlist = curl_slist_append(headerlist, mkdir.c_str());
|
|
|
/* 设置FTP命令行选项 */
|
|
|
curl_easy_setopt(m_curl, CURLOPT_QUOTE, headerlist);
|
|
@@ -684,12 +665,12 @@ bool CurlFtp::createDirectory(const std::string& ftpDir)
|
|
|
// 启用持久连接
|
|
|
// curl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
|
|
|
- SPDLOG_DEBUG("Create dir: {}", dirTmp);
|
|
|
+ SPDLOG_DEBUG("Create remote dir: {}", dirTmp);
|
|
|
// CURLcode res = curl_easy_perform(curl);
|
|
|
bool ret = performCurl(m_curl);
|
|
|
if(!ret)
|
|
|
{
|
|
|
- SPDLOG_ERROR("Failed to create FTP Dir");
|
|
|
+ SPDLOG_ERROR("Failed to create remote Dir");
|
|
|
}
|
|
|
|
|
|
// curl_easy_cleanup(curl);
|
|
@@ -1336,5 +1317,85 @@ bool CurlFtp::setSftp(CURL* curl)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+/* 检查FTP文件夹是否存在 */
|
|
|
+bool CurlFtp::checkFtpDirExist(const std::string& dir)
|
|
|
+{
|
|
|
+ /* 检查传入的文件夹 */
|
|
|
+ auto dirTmp = checkDirPath(dir);
|
|
|
+ resetCurl(m_curl);
|
|
|
+ std::string ftpUrl = m_ftpUrl + dir;
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_URL, ftpUrl.c_str());
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_USERNAME, m_username.c_str());
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_PASSWORD, m_password.c_str());
|
|
|
+ /* 获取文件夹是否存在,不需要接收文件 */
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_HEADER, 1L);
|
|
|
+
|
|
|
+ /* 设置SFTP */
|
|
|
+ setSftp(m_curl);
|
|
|
+ /* 启用调试信息 */
|
|
|
+ if(m_enableCurlDebug)
|
|
|
+ {
|
|
|
+ curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1L);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 启用持久连接 */
|
|
|
+ // curl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);
|
|
|
+ /* 这里只需要执行一次 */
|
|
|
+ CURLcode res = curl_easy_perform(m_curl);
|
|
|
+ bool result = true;
|
|
|
+ if(res == CURLE_REMOTE_FILE_NOT_FOUND)
|
|
|
+ {
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+ else if(res != CURLE_OK)
|
|
|
+ {
|
|
|
+ // SPDLOG_ERROR("Check remote dir error, error code: {} ,{}", (int)res, curl_easy_strerror(res));
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* sftp即使远程文件夹不存在也会返回OK,这里使用http进行检查 */
|
|
|
+ // long response_code = -1;
|
|
|
+ // res = curl_easy_getinfo(m_curl, CURLINFO_HTTP_CONNECTCODE, &response_code);
|
|
|
+ // if((res == CURLE_OK) && (response_code == 0))
|
|
|
+ // {
|
|
|
+ // SPDLOG_ERROR("Remote directory not found: {}", dir);
|
|
|
+ // result = false;
|
|
|
+ // }
|
|
|
+ // SPDLOG_DEBUG("response_code: {}", response_code);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+/* 检查SFTP文件夹是否存在,这里通过列出上一层的文件夹中的内容,然后进行对比判断的 */
|
|
|
+bool CurlFtp::checkSftpDirExist(const std::string& dir)
|
|
|
+{
|
|
|
+ /* 取出上一层文件夹路径 */
|
|
|
+ std::string parentDir = std::filesystem::path(dir).parent_path().string();
|
|
|
+ // SPDLOG_DEBUG("Parent dir: {}", parentDir);
|
|
|
+ std::vector<std::string> vecDir;
|
|
|
+ bool ret = getDirList(parentDir, vecDir);
|
|
|
+ if(!ret)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("Failed to check sftp dir: {}", dir);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ /* 取出本层文件夹名称 */
|
|
|
+ std::string dirName = std::filesystem::path(dir).filename().string();
|
|
|
+ // SPDLOG_DEBUG("Dir name: {}", dirName);
|
|
|
+ /* 判断是否存在 */
|
|
|
+ bool result = false;
|
|
|
+ for(const std::string& str : vecDir)
|
|
|
+ {
|
|
|
+ if(str == dirName)
|
|
|
+ {
|
|
|
+ result = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|