Browse Source

V0.3.0
1、完成了CurlFTP的上传下载功能

Apple 5 months ago
parent
commit
d74df2a94c
3 changed files with 114 additions and 12 deletions
  1. 2 2
      Libraries/Libraries.cmake
  2. 111 10
      common/CurlFtp/CurlFtp.cpp
  3. 1 0
      common/CurlFtp/CurlFtp.h

+ 2 - 2
Libraries/Libraries.cmake

@@ -55,7 +55,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
 elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
     message(STATUS "Using ${CMAKE_SYSTEM_NAME} System")
     #添加Curl库
-    set(CURL_DIR ${CMAKE_CURRENT_LIST_DIR}/linux_gcc8.3/lib/cmake/CURL)
+    # set(CURL_DIR ${CMAKE_CURRENT_LIST_DIR}/linux_gcc8.3/lib/cmake/CURL)
     set(hiredis_DIR ${CMAKE_CURRENT_LIST_DIR}/linux_gcc8.3/lib/cmake/hiredis)
     if(ENABLE_SPDLOG_STATIC_LIB)
         set(fmt_DIR ${CMAKE_CURRENT_LIST_DIR}/linux_gcc8.3_static/lib/cmake/fmt)
@@ -76,7 +76,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/LHQLog)
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/LHHTTPAPI)
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/OpenSSL-1.1.1)
 #添加CURL的路径,目前Linux shying单独编译的,使用上面的OpenSSL库
-# list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CURL)
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CURL)
 
 #搜索所有的库
 find_package(fmt REQUIRED)

+ 111 - 10
common/CurlFtp/CurlFtp.cpp

@@ -73,23 +73,37 @@ static int writeStringListCallback(void* buffer, size_t size, size_t nmemb, void
 /**
  * @brief 写入文件回调函数
  * 
- * @param contents 下载到的数据内容
+ * @param contents 读取到的数据内容
  * @param size 数据大小
  * @param nmemb 数据单位
  * @param pFile 文件指针
- * @return size_t 写入的大小
+ * @return size_t 实际读取的大小
  */
 static size_t writeDataCallBack(void* contents, size_t size, size_t nmemb, std::ostream* pFile)
 {
     pFile->write(reinterpret_cast<char*>(contents), size * nmemb);
-    // if(pFile->fail())
-    // {
-    //     FMTLOG_ERROR("Failed to write data to file");
-    //     return 0;
-    // }
     return size * nmemb;
 }
 
+/**
+ * @brief 读取文件回调函数
+ * 
+ * @param contents 下载到的数据内容
+ * @param size 数据大小
+ * @param nmemb 数据单位
+ * @param pFile 文件指针
+ * @return size_t 写入的大小
+ */
+static size_t readDataCallBack(void* contents, size_t size, size_t nmemb, std::istream* pFile)
+{    
+    pFile->read(reinterpret_cast<char*>(contents), size * nmemb);
+    /* 获取读取到的字节数,可能读取到文件末尾,所以不能直接使用传入的字节数 */
+    size_t readSize = pFile->gcount();
+
+    return readSize;
+    
+}
+
 /**
  * @brief 上传和下载进度回调函数,这个函数kennel会被多次调用,即使是没有在下载的时候,因此需要判断传入的数据是否是0
  *        必须将 CURLOPT_NOPROGRESS 设为 0 才能真正调用该函数。
@@ -119,13 +133,13 @@ static int progress_callback(void *clientp,
         /* 计算进度,百分比 */
         double downloadPercent = (double)dlnow / (double)dltotal * 100;
         /* 使用回车刷新这一行 */
-        FMTLOG_DEBUG_NON("Download Total / now : {} / {}, {:.1f}%\r", dltotal, dlnow, downloadPercent);
+        FMTLOG_DEBUG_NON("Download Total / now : {} / {}, {:.2f}%\r", dltotal, dlnow, downloadPercent);
     }
     /* 正在上传 */
     else if(ultotal > 0)
     {
         double uploadPercent = (double)ulnow / (double)ultotal * 100;
-        FMTLOG_DEBUG_NON("Upload Total / now : {} / {}, {:.1f}%\r", ultotal, ulnow, uploadPercent);
+        FMTLOG_DEBUG_NON("Upload Total / now : {} / {}, {:.2f}%\r", ultotal, ulnow, uploadPercent);
     }
 
     return 0;
@@ -703,8 +717,95 @@ bool CurlFtp::downloadFile(const std::string& remoteFile, const std::string& loc
  */
 bool CurlFtp::uploadFile(const std::string& localFile, const std::string& remoteFile)
 {
+    if(m_ftpUrl.empty())
+    {
+        FMTLOG_ERROR("ftpUrl is empty");
+        return false;
+    }
+    /* 检查本地文件是否存在 */
+    if(!std::filesystem::exists(localFile))
+    {
+        FMTLOG_ERROR("Local file is not exist: {}", localFile);
+        return false;
+    }
+    /* 检查FTP文件名是否符合规范 */
+    std::string remoteFileTmp = checkFilePath(remoteFile);
+    std::string remoteDirTmp = remoteFileTmp.substr(0, remoteFileTmp.find_last_of("/"));
+    /* 检查远程FTP上的文件夹是否存在,不存在则创建 */
+    if(!isDirExist(remoteDirTmp))
+    {
+        if(!createDirectories(remoteDirTmp))
+        {
+            // FMTLOG_ERROR("Failed to create remote dir: {}", remoteFileTmp);
+            return false;
+        }
+    }
+    /* 拼接远程文件的url */
+    std::string ftpUrl = m_ftpUrl + remoteFileTmp;
+    
+    /* 打开文件 */
+    std::ifstream ifs;
+    ifs.open(localFile, std::ios::in | std::ios::binary);
+    if(!ifs.is_open())
+    {
+        FMTLOG_ERROR("Failed to open local file: {}", localFile);
+        return false;
+    }
+    /* 获取文件大小 */
+    // auto startPos = ifs.tellg();
+    ifs.seekg(0, std::ios::end);
+    auto fileSize = ifs.tellg();
+    /* 恢复指针到文件头 */
+    ifs.seekg(0, std::ios::beg);
+    FMTLOG_DEBUG("File size: {}", (long)fileSize);
 
-    return true;
+    CURL* curl = nullptr;
+    curl = curl_easy_init();
+    if(curl == nullptr)
+    {
+        FMTLOG_ERROR("curl init failed !");
+        ifs.close();
+        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_FOLLOWLOCATION, 1L);
+    /* 启用上传 */
+    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+    /* 设置回调函数 */
+    curl_easy_setopt(curl, CURLOPT_READFUNCTION, readDataCallBack);
+    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_XFERINFOFUNCTION, progress_callback);
+    curl_easy_setopt(curl, CURLOPT_XFERINFODATA, nullptr);
+    /* 启用下载进度回调函数 */
+    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
+    /* 发送请求 */
+    CURLcode res = curl_easy_perform(curl);
+    bool result = true;
+    if(res != CURLE_OK)
+    {
+        FMTLOG_ERROR("Upload file failed, error code: {} ,{}", (int)res, curl_easy_strerror(res));
+        FMTLOG_ERROR("ftpUrl = {}", ftpUrl);
+        result = false;
+    }
+    /* 关闭文件,清理curl */
+    ifs.close();
+    curl_easy_cleanup(curl);
+    /* 打印一个换行符 */
+    FMTLOG_DEBUG_NON("\n");
+
+    return result;
 }
 
 

+ 1 - 0
common/CurlFtp/CurlFtp.h

@@ -15,6 +15,7 @@
  *
  *     1.默认超时时间是10s
  *     2.默认端口是21
+ *     3.设置好IP和端口号后,后续输入的文件路径都是想对你路径,无需添加IP和端口号
  * 
  */