c++使用libcurl开发的sftp、ftp下载远程文件目录

curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, callback);

static size_t callback(char* data, size_t size, size_t nmemb, void* buffer_in);

这个回调函数的原型一定要和官方文档里面的一样,否则可能会出各种奇怪的错误。注意,一定要是static函数,返回值、参数值一定要一样。回调的返回值一定要正确,不正确会导致回调停掉。

测试返回nmemb应该是正确的。

用了CURLOPT_WRITEFUNCTION,就一定要用CURLOPT_WRITEDATA

curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &ftpfile);这里最后那个参数一定要是struct类型,这个参数在callback里面是它的第四个参数。可以自定义。

如果不用CURLOPT_WRITEFUNCTION,那么CURLOPT_WRITEDATA的参数一定是个FILE*类型。官方文档上介绍这个操作默认是用fwrite直接写文档的。

CURLOPT_DIRLISTONLY可以直接获取服务器的文件列表。

curl_global_init(CURL_GLOBAL_ALL);   //全局初始化,而且只能调用一次

        CURL_GLOBAL_ALL//这个flag是表示初始化一切可能,官网文档可以查到

curl_global_cleanup(); //全局回收资源

下载文件:    //结构体也可以弄成C++文件流,只需要稍微修改一下下载的回调即可

struct downLoad
{
    FILE* filestream;
    std::string filename;
};

struct downLoad down_file;

{

    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, “sftp://ip:port/filename”);
    curl_easy_setopt(curl, CURLOPT_USERNAME, "username");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, down_file_call_back);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &down_file_);
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK)
    {
        std::cout << "remote file error:" << res << std::endl;
        curl_easy_strerror(res);
        return -1;
    }
    curl_easy_cleanup(curl);

 }

size_t CRemoteFileMan::down_file(char* data, size_t size, size_t nmemb, void* buffer_in)  
{
    struct downLoad* temp = (struct downLoad*)buffer_in; 
    if (temp->filestream == NULL && temp)
    {
        fopen_s(&temp->filestream, temp->filename.c_str(), "wb+");
        if (!temp->filestream)
            return - 1;
    }
    return fwrite(data, size, nmemb, temp->filestream);
}

获取远程服务器下的文件列表:

struct fileList
{
    std::string filename;
};

struct fileList file_list;

{

    CURL* curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, “sftp://ip:port/foldername/”);
        curl_easy_setopt(curl, CURLOPT_USERNAME, "username");
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
        curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_list);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file_list);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            std::cout << "remote file error:" << res << std::endl;
            curl_easy_strerror(res);
        }
    }
    curl_easy_cleanup(curl);

}

size_t CRemoteFileMan::get_list(char* data, size_t size, size_t nmemb, void* buffer_in)
{
    struct fileList* out = (struct fileList*)buffer_in;
    out->filename.append(data);
    return nmemb;    //这个返回值不正确的话,回调会结束

判断远程文件是文件夹还是目录:

{

    CURL* curl = curl_easy_init();
    bool remoteFile = false;
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, “sftp://ip:port/foldername/”);                                                                                                               //   “sftp://ip:port/foldername/filename/”
        curl_easy_setopt(curl, CURLOPT_USERNAME, "username");
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
        curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);    //设置这个参数的目的是看远程有没有这

                                                                                           //个指定的文件
        CURLcode res = curl_easy_perform(curl); 
        if (res != CURLE_OK)
            remoteFile = false;
        else
            remoteFile = true;
        curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);  //获取这个文件的远程列表,文件夹

                                                                                                //会返回一个列表,文件则出错,

                                                                                                //这样可以达到判断的目的
        res = curl_easy_perform(curl);
        if (res == CURLE_OK && remoteFile)
        {
            std::cout << "this is folder"<< std::endl;
            return true;
        }
    }
    std::cout << "this is file" << std::endl;
    return false;

}

递归整个需要下载的目录,然后在本地指定的目录建立相应文件夹,下载完相应文件下的文件即可完成远程目录遍历下载。

//libcurl 下载ftp服务器全部文件 - CodeAntenna

这个链接是我在网上找到的一篇下载整个目录的文章,可以直接用,大致区别就是,这篇文章是将文件列表放在一个自己创建的txt文档内,然后用getline获取txt文档内的一行内容,然后判断是不是文件夹,文件夹就递归调用获取列表的函数并建立文件夹,否则下载该文件。

我自己则是想的将文件列表放在一个std::string字符串内,然后根据linux、windows的特性,分割字符串,获取列表,然后遍历列表,是文件夹就递归,不是文件夹就下载。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++使用libcurl库可以方便地进行网络通信,包括发送HTTP请求、下载文件等操作。下面是使用libcurl的一般步骤: 1. 引入头文件:在代码中引入libcurl的头文件,通常是`#include <curl/curl.h>`。 2. 初始化和清理:在使用libcurl之前,需要调用`curl_global_init()`函数进行初始化,并在使用完毕后调用`curl_global_cleanup()`函数进行清理。 3. 创建和配置CURL对象:使用`curl_easy_init()`函数创建一个CURL对象,并使用`curl_easy_setopt()`函数设置相关选项,如设置请求的URL、设置请求的方法、设置请求头等。 4. 执行请求:使用`curl_easy_perform()`函数执行请求,该函数会阻塞直到请求完成。 5. 处理响应:可以通过设置回调函数来处理响应数据,如保存到文件、打印到控制台等。 6. 清理资源:使用`curl_easy_cleanup()`函数释放CURL对象。 下面是一个简单的示例代码,演示了如何使用libcurl发送GET请求并将响应打印到控制台: ```cpp #include <iostream> #include <curl/curl.h> // 回调函数,处理响应数据 size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response) { size_t totalSize = size * nmemb; response->append((char*)contents, totalSize); return totalSize; } int main() { CURL* curl; CURLcode res; std::string response; // 初始化 curl_global_init(CURL_GLOBAL_DEFAULT); // 创建CURL对象 curl = curl_easy_init(); if (curl) { // 设置请求的URL curl_easy_setopt(curl, CURLOPT_URL, "http://example.com"); // 设置回调函数 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); // 执行请求 res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } // 打印响应数据 std::cout << response << std::endl; // 清理资源 curl_easy_cleanup(curl); } // 清理 curl_global_cleanup(); return 0; } ``` 这只是一个简单的示例,libcurl还提供了更多的功能和选项,可以根据具体需求进行配置和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值