当前位置: 首页 > news >正文

QT中使用libcurl库实现到ftp服务器的上传和下载

最近新开了一个项目需要用到ftp服务器,之前没接触过这方面,刚开始觉得很简单,一两天应该就可以搞好,谁知道花了我接近一周时间,此时此刻!!!我实现了,赶紧记录一下哈哈

  1. libcurl库的下载,网上很多都需要下载之后编译,我嫌浪费时间就找了一个版本的用,(夸克网盘)
    链接:https://pan.quark.cn/s/64d2067a6657
    提取码:pVU5
  2. 首先就是加入库和include包含文件,这些不赘述了,有问题可以问我,看到会回的,知无不言;
  3. 先说上传本地文件到ftp服务器

//上传

void connectANDUploadFile(const QString& ftpUrl, const QString& username, const QString& password, const QString& localFilePath)
{CURL* curl;CURLcode res;FILE* file = fopen(localFilePath.toStdString().c_str(), "rb"); // 打开本地文件if (!file){qDebug() << "Error opening file for downloading!";return;}curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化 libcurlcurl = curl_easy_init(); // 创建一个 curl 会话if (!curl){qDebug() << "Failed to create CURL session";fclose(file);curl_global_cleanup();return;}curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);// 设置 FTP 服务器地址curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.toStdString().c_str());// 设置 FTP 服务器的用户名和密码curl_easy_setopt(curl, CURLOPT_USERPWD, (username + ":" + password).toStdString().c_str());// 设置回调函数来处理下载数据//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, discardfunc);// 使用 FTP 的目录列表命令curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LIST");curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "STOR");//显示创建ftp上不存在的文件curl_easy_setopt(curl, CURLOPT_READFUNCTION, readfunc);curl_easy_setopt(curl, CURLOPT_READDATA, file); // 文件指针作为目标// 设置超时时间(例如 30 秒)curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);// 使用被动模式(通常需要)curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);//curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); // 要求服务器返回200 OK才认为成功// 执行 FTP 连接并上传文件res = curl_easy_perform(curl);long Ftp_code = 0;curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &Ftp_code);if (Ftp_code != 200) {qDebug() << "FTP 错误码: " << Ftp_code;}// 检查连接和下载是否成功if (res != CURLE_OK){qDebug() << "FTP connection or download failed: " << curl_easy_strerror(res);}else{qDebug() << "File downloaded successfully!";}// 关闭文件fclose(file);// 清理curl_easy_cleanup(curl);curl_global_cleanup(); // 清理 libcurl
}
size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{FILE *f = (FILE*)stream;size_t n;if (ferror(f)){return CURL_READFUNC_ABORT;}n = fread(ptr, size, nmemb, f) * size;return n;
}

//调用方法

 QString localFilePath = "E:/LocalFTP";  // 本地上传路径,你自己的文件目录QString ftpUrl = "ftp://你的服务器/upload/";  // FTP 服务器文件路径,upload要确保服务器上有这个文件夹QString username = "user";  // FTP 服务器用户名QString password = "118811";  // FTP 服务器密码QList<QString> UpFileNameList = QFileDialog::getOpenFileNames(this, "OpenFiles", "", "");//因为我要上传多个文件,所以直接用了选择哪些上传哪些foreach(const QString & FileName, UpFileNameList){QFileInfo FileInfo(FileName);connectANDUploadFile(ftpUrl+ "/" + FileInfo.fileName(), username, password, localFilePath + "/" + FileInfo.fileName());}

注意的地方:首先就是设置那个上传CURLOPT_UPLOAD必不可少,其次是LIST命令,网上搜了说是LIST和STOR命令可在远程文件夹下没有上传的文件名时自动创建该文件,所以我加了。
很多时候可能都是由于上传路径的问题导致出错,因为上传路径必须也要有相应的文件名才行,只有文件夹不行

下载:由于也是下载远程文件夹下的很多文件,所以我这里首先要获取到远程文件夹下的文件名,然后再写入数据,实现如下:

//获取ftp服务器目录下的所有文件名并写入list中
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp)
{std::string* data = static_cast<std::string*>(userp);size_t totalSize = size * nmemb;data->append(static_cast<char*>(contents), totalSize);return totalSize;
}
QList<QString> parseFileList(const std::string& rawData)
{QList<QString> fileList;std::istringstream stream(rawData);std::string line;while (std::getline(stream, line)){if (!line.empty()){std::istringstream lineStream(line);std::string segment;std::string fileName;while (lineStream >> segment){fileName = segment; // 获取最后一个部分作为文件名}fileList.append(QString::fromStdString(fileName)); // 添加文件名到列表}}return fileList;
}
QList<QString> getDirectoryFiles(const QString& url, const QString& username, const QString& password)
{QList<QString> fileList;CURL* curl;CURLcode res;curl = curl_easy_init();if (curl){std::string readBuffer;// 设置 URLcurl_easy_setopt(curl, CURLOPT_URL, url.toStdString().c_str());// 设置用户名和密码std::string userPwd = username.toStdString() + ":" + password.toStdString();curl_easy_setopt(curl, CURLOPT_USERPWD, userPwd.c_str());// 使用 FTP 的目录列表命令curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LIST");// 设置写回调函数curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);// 执行请求res = curl_easy_perform(curl);if (res != CURLE_OK){qDebug() << "curl_easy_perform() failed:" << curl_easy_strerror(res);}else{// 解析返回的目录列表fileList = parseFileList(readBuffer);}// 清理curl_easy_cleanup(curl);}return fileList;
}
//将对应文件名下的数据写入对应文件的回调函数
size_t write_callback(void* ptr, size_t size, size_t nmemb, FILE* stream)
{size_t written = fwrite(ptr, size, nmemb, stream); // 将数据写入文件return written;
}
void connectANDdownloadFile(const QString& ftpUrl, const QString& username, const QString& password, const QString& localFilePath)
{CURL* curl;CURLcode res;FILE* file = fopen(localFilePath.toStdString().c_str(), "wb"); // 打开本地文件if (!file){qDebug() << "Error opening file for downloading!";return;}curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化 libcurlcurl = curl_easy_init(); // 创建一个 curl 会话if (!curl){qDebug() << "Failed to create CURL session";fclose(file);curl_global_cleanup();return;}// 设置 FTP 服务器地址curl_easy_setopt(curl, CURLOPT_URL, ftpUrl.toStdString().c_str());// 设置 FTP 服务器的用户名和密码curl_easy_setopt(curl, CURLOPT_USERPWD, (username + ":" + password).toStdString().c_str());// 设置回调函数来处理下载数据curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); // 文件指针作为目标// 设置超时时间(例如 30 秒)curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);// 执行 FTP 连接并下载文件res = curl_easy_perform(curl);// 检查连接和下载是否成功if (res != CURLE_OK){qDebug() << "FTP connection or download failed: " << curl_easy_strerror(res);}else{qDebug() << "File downloaded successfully!";}// 关闭文件fclose(file);// 清理curl_easy_cleanup(curl);curl_global_cleanup(); // 清理 libcurl
}

//调用方法

QString localFilePath = "E:/DownLoadFile/upload/";  // 本地保存路径
QString ftpUrl = "ftp://你的ftp服务器/uplaod/";  // FTP 服务器文件路径
QString username = "user";  // FTP 服务器用户名
QString password = "118811";  // FTP 服务器密码
QList<QString> files = getDirectoryFiles(ftpUrl, username, password);
foreach(const QString & FileName, files)
{connectANDdownloadFile(ftpUrl+ FileName, username, password, localFilePath + FileName);}

注意:这里比较麻烦的就是先要获取远程目录下的文件,再根据文件名下载同名文件到本地文件中
OK,暂时分享到这,代码还是有点冗余,需要优化,后续会在读取和写入使用定时器确保不卡顿,还要完成实时更新服务器上的文件以及下载,同步问题都需要解决,但好在第一步终于踏出去了!

相关文章:

  • 大话软工笔记—分析模型
  • Elasticsearch:spring2.x集成elasticsearch8.x
  • 基于Java(SpringBoot、Mybatis、SpringMvc)+MySQL实现(Web)小二结账系统
  • 网络安全全景解析
  • 多层PCB技术解析:从材料选型到制造工艺的深度实践
  • 【联网玩具】EN 18031欧盟网络安全认证
  • 【Linux】 Linux 进程控制
  • 用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`
  • 数据库三范式设计---小白初学+案例引入
  • 数据分析实战2(Tableau)
  • SpringCloud-基于SpringAMQP实现消息队列
  • 矩阵分解相关知识点总结(二)
  • 使用 C/C++ 和 OpenCV 添加图片水印
  • 接IT方案编写(PPT/WORD)、业务架构设计、投标任务
  • DAY 21 常见的降维算法
  • OpenAI技术路线急转:从TypeScript到Rust的Codex CLI重构内幕
  • Spring WebFlux 整合AI大模型实现流式输出
  • Python-内置函数
  • MCP协议在LLM系统中的架构与实现原理研究
  • Cursor 集成 Figma MCP 实现阅读理解原型图生成方案
  • 做网站的价格 外贸/武汉百度
  • 服务好的高端网站建设公司/seo推广方法集合
  • 网站建设项目分期/seo外包 靠谱
  • 武汉做网站小程序哪家公司好/营销方案ppt
  • 学做预算网站/百度企业推广怎么收费
  • 品牌建设的措施建议/seo入门培训学校