使用Libcurl从FTP服务器文件下载多个文件

时间:2012-08-24 12:01:13

标签: c++ ftp download libcurl

我使用以下代码从FTP服务器下载所有文件

遵循的步骤是: 1.创建文件的FTP列表

    getFTPList(string sHost, string sUser, string sPass, string sUri)
{
  CURL *curl;
  CURLcode res;
  FILE *ftplister;
  string host = "ftp://";
  host += sHost;
  host += "/sample/";
  string furl = host + sUri;  
  string usrpwd = sUser;
  usrpwd += ":";
  usrpwd += sPass;
  /* local file name to store the file as */ 
  ftplister = fopen("ftp-list", "wb"); /* b is binary, needed on win32 */   
  curl = curl_easy_init();
  if(curl) {
    /* Get a file listing from sunet */ 
    curl_easy_setopt(curl, CURLOPT_URL, furl.c_str() );
    curl_easy_setopt(curl, CURLOPT_USERPWD, usrpwd.c_str());
    curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, TRUE);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_list);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftplister);
    res = curl_easy_perform(curl);
    /* Check for errors */ 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */ 
    curl_easy_cleanup(curl);
  } 
  fclose(ftplister); /* close the local file */   
}
  1. 使用此列表下载递归调用下载函数的文件

    int main(){
    FILE *ftpfile; 
    string line;
    ftpfile = fopen("ftp-list", "r"); 
    ifstream infile("ftp-list");
     while ( getline(infile, line) )
     {
        string url, ofname, surl = "ftp://myhost/uploader/", sfname = "C:\\CNAP\\";        
        url = surl + line;
        ofname = sfname +line;
        cout<<url<<"   "<<ofname<<endl;
        char* theVal ;
        char* theStr ;
        theVal = new char [url.size()+1];
        theStr = new char [ofname.size()+1];
        strcpy(theVal, url.c_str());
        strcpy(theStr, ofname.c_str());       
        downloadFile(theVal, theStr);
     }
    return 0;
    }
    
  2. 现在下载功能:

    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written;
        written = fwrite(ptr, size, nmemb, stream);
        return written;
       }
    
       void downloadFile(const char* url, const char* ofname)
       {
        CURL *curl;
            FILE *fp;
            CURLcode res;        
            curl = curl_easy_init();
            if (curl){
                fp = fopen(ofname,"wb");
                curl_easy_setopt(curl, CURLOPT_URL, url);
                curl_easy_setopt(curl, CURLOPT_USERPWD, "user:pass");
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                res = curl_easy_perform(curl);
                curl_easy_cleanup(curl);
                fclose(fp);
            }
         }
    

    它在实现时效果很好,但仅用于下载文本文件或带文本的文件,如果我下载图像或docx或aa zip或rar,或者对于任何非文本文件失败,它无法打开下载后(说无效文件)。

    我不确定我错过了什么,我们将不胜感激。

    我知道这是一种低效的编码方式,但我只需要下载正确(任何文件)。努力提高效率是我的下一个议程。

    PS:使用此处使用的此方法 Downloading multiple files with libcurl in C++

    谢谢

3 个答案:

答案 0 :(得分:1)

下载时的文件需要作为二进制文件打开

fp = fopen(ofname,"wb");

感谢Rob的帮助

答案 1 :(得分:0)

这是猜测。: 尝试清除选项CURLOPT_TRANSFERTEXTCURLOPT_CRLF

Refernce:

答案 2 :(得分:0)

#include <stdio.h> 
#include <curl/curl.h>
#include <curl/easy.h>
#include <string>
#include <iostream>
#include <fstream>

using namespace std;

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream);

void getFileList(
    const string &strHost, 
    const string &strUri, 
    const string &strUser, 
    const string &strPassWord, 
    const string &strTargetFile
);

void downloadAllFiles(
    const string &strFtpListFile, 
    const string &strHost, 
    const string &strUri, 
    const string &strUser, 
    const string &strPassWord, 
    const string &strSaveTargetFolder
);



int main(void) 
{
    string strHost = "ftp://192.168.0.1:22";
    string strUri = "/cobus/test/";
    string strUser = "cobus";
    string strPassWord = "password";
    string strTargetFile = "c:\\cobus\\ftpList.txt";
    string strSaveDestFolder = "c:\\cobus\\";

    getFileList(strHost, strUri, strUser, strPassWord, strTargetFile);

    downloadAllFiles(
        strTargetFile, 
        strHost, 
        strUri, 
        strUser, 
        strPassWord, 
        strSaveDestFolder
    );
}

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) 
{
    size_t written = fwrite(ptr, size, nmemb, stream);
    return written;

}


void getFileList(const string &strHost, const string &strUri, 
const string &strUser, const string &strPassWord, const string &strTargetFile)
{
    CURL *curl;
    CURLcode res;
    FILE *ftplister;
    string strSourceFullUri = strHost + strUri;
    string strUserPwInfo = strUser + ":" + strPassWord;

    /* local file name to store the file as */ 
    ftplister = fopen(strTargetFile.c_str(), "wb"); /* b is binary, needed on win32 */

    curl = curl_easy_init();

    if(curl) 
    {
        /* Get a file listing from sunet */ 
        curl_easy_setopt(curl, CURLOPT_URL, strSourceFullUri.c_str() );
        curl_easy_setopt(curl, CURLOPT_USERPWD, strUserPwInfo.c_str());
        curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, TRUE);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftplister);
        res = curl_easy_perform(curl);

        /* Check for errors */ 
        if(res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res));

        /* always cleanup */ 
        curl_easy_cleanup(curl);
    } 

    fclose(ftplister); /* close the local file */   

}

void downloadAllFiles(const string &strFtpListFile, const string &strHost, 
    const string &strUri, const string &strUser, const string &strPassWord, 
    const string &strSaveDestFolder)
{
    FILE *ftpFile = NULL;
    string strFileName = "";

    ifstream infile(strFtpListFile.c_str());

    if(!infile.is_open())
    {
        cerr << "can not open ftpList.txt" << endl;
        return ;
    }

    /* ftpList.txt get data, line by line, processing */
    while(getline(infile, strFileName))
    {
        CURL *curl;
        FILE *destFilePath;
        CURLcode res;        

        curl = curl_easy_init();

        if (curl)
        {
            destFilePath = fopen((strSaveDestFolder+strFileName).c_str(),"wb");
            curl_easy_setopt(curl, CURLOPT_URL, (strHost+strUri+strFileName).c_str());
            curl_easy_setopt(curl, CURLOPT_USERPWD, (strUser+":"+strPassWord).c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, destFilePath);
            res = curl_easy_perform(curl);

            curl_easy_cleanup(curl);

            fclose(destFilePath);
        }
    }// end while
}

我尽可能地立刻看到了Vivian Lobo的内容。 我试着测试Vivian Lobo的发言。这很好用。

stackOverFlow很难编写代码。 我如何评价Vivian的lobo文章?