ubuntu下linux:curl使用ftp获取服务器上指定目录的所有文件集合以及下载

curl使用ftp获取服务器上指定目录的所有文件集合以及下载

直接编译可用,注意修改测试main函数内的字符串,注释我觉得写的挺详细了,跑不起来的评论区可问

头文件

#ifndef FTP_DOWNLOAD_H
#define FTP_DOWNLOAD_H
#include <iostream>
#include <functional>
#include <memory>
#include <vector>
#include<cstdlib>
#include <ctime>
using namespace std;
using OutPutList = vector<string>;
#define FTPBODY "ftp-list"

struct FtpFile
{
	string local;
	FILE *stream;
};

class FtpDownloadder
{
public:
       /**
        * @brief Construct a new Ftp Downloadder object
        * 
        * @param ip 
        * @param port 
        * @param username 
        * @param password 
        */
       FtpDownloadder(const char *ip,const char *port,const char *username,const char *password);
	~FtpDownloadder();

       /**
        * @brief 获取指定文件夹下所有文件名
        * 
        * @param folderName 指定文件夹名称
        *     (从登录用户家目录开始算,for example: /home/user/targetFolder  , you can give a param with "targetFolder")
        * @return OutPutList 该文件夹下的所有文件名集合,包含拓展名
        */
       OutPutList getAllItem(const string& folderName);
       /**
        * @brief  更新本地缓存
        * 
        * @param fileList ftp服务器上的文件集合
        * @param remotFolderPath ftp服务器上的文件夹路径
        *     (从登录用户家目录开始算,for example: /home/user/targetFolder  , you can give a param with "targetFolder")
        * @param localCacheFolder 本地缓存文件夹
        * @return true successful
        * @return false faild
        */
       bool flashLocalCache(const OutPutList& fileList, const string& remotFolderPath, const string& localCacheFolder);
       /**
        * @brief 下载文件
        * 
        * @param filePath ftp服务器上的文件路径
        *     (从登录用户家目录开始算,for example: /home/user/targetFolder/test.tgz  , you can give a param with "targetFolder/test.tgz")
        * @param localFolderPath 本地存储的文件夹全路径,默认当前程序文件夹
        * @return string 本地存储完整路径 
        */
       string downLoadFile(const string& filePath,const string& localFolderPath = "/home/root/test");
private:
       string m_url;
       string m_username;
	string m_password;

};

std::shared_ptr<FtpDownloadder> createFtpPtr(const char *ip,const char *port,const char *username,const char *password);

#endif 

cpp

#include "download.hpp"
#include <stdio.h>
#include <iostream>
#include <curl/curl.h>
#include <fstream>
#include <string.h>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h> 
#include <fcntl.h>
using namespace std;

/* <DESC>
 * Similar to ftpget.c but also stores the received response-lines
 * in a separate file using our own callback!
 * </DESC>
 */
static size_t
write_response(void *ptr, size_t size, size_t nmemb, void *data)
{
  FILE *writehere = (FILE *)data;
  return fwrite(ptr, size, nmemb, writehere);
}
/**
 * @brief Get the File Name object
 * 
 * @param content 
 * @param output 
 * @return true 是文件
 * @return false 不是文件
 */
static bool getFileName(const string& content, char* output)
{
	strncpy(output,content.c_str(),1);
	if (strcmp(output,"d") == 0)
	{
		return false;
	}
    strncpy(output,content.c_str()+56,content.length()-56);
	return true;
}
/**
 * @brief  验证文件夹是否存在,不存在则创建
 * 
 * @param path 
 * @return true 
 * @return false 
 */
static bool checkFolderExistAndMKDIR(const string& path)
{
	struct stat file_info;  
	if(stat(path.c_str(), &file_info) != 0)  
	{
		string tt = "mkdir -p ";
		tt+=path;
		system(tt.c_str());
	}
}
/**
 * @brief  文件写入本地
 * 
 * @param buffer 
 * @param size 
 * @param nmemb 
 * @param stream 
 * @return int 
 */
int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
	struct FtpFile *out=(struct FtpFile *)stream;
	if(out && !out->stream)
	{	  
		/* open file for writing */ 
		out->stream=fopen((out->local).c_str(), "ab+");
		if(!out->stream)
		{
			cout << "failure, can't open "+out->local+" to write"<<endl;
			return -1; /* failure, can't open file to write */ 
		}
	}
	return fwrite(buffer, size, nmemb, out->stream);
}

FtpDownloadder::FtpDownloadder(const char *ip,const char *port,const char *username,const char *password)
{
	m_url = "ftp://"+string(ip)+":"+string(port);
	m_username = username;
	m_password = password;
};
FtpDownloadder::~FtpDownloadder(){};

OutPutList FtpDownloadder::getAllItem(const string& folderName)
{
	OutPutList outPutList;
	// TODO
	CURL *curl;
    CURLcode res;
    FILE *ftpfile;
    /* local file name to store the file as */
    ftpfile = fopen(FTPBODY, "wb"); /* b is binary, needed on win32 */

    curl = curl_easy_init();
    if(curl)
    {
        /* Get a file listing from ftp server */
		string temp_url = m_url + "/"+folderName + "/";
        curl_easy_setopt(curl, CURLOPT_URL, temp_url.c_str());
		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_WRITEDATA, ftpfile);

        res = curl_easy_perform(curl);
        /* Check for errors */
        if(res != CURLE_OK)
		{
			fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
			fclose(ftpfile);
			return outPutList;
		}
        /* always cleanup */
        curl_easy_cleanup(curl);
    }
    fclose(ftpfile); /* close the local file */

	string content;
	char buffer[312];
	ifstream infile(FTPBODY);
	if ( !infile)
	{
		cout<<"ifstream infile(\"ftp-list\") failed"<<endl;
		return outPutList;
	}
	
    while (getline(infile,content))
    {		
        memset(buffer,0,312);
        auto temp_res = getFileName(content,buffer);
		if (!temp_res)
		{
			continue;
		}
		outPutList.push_back(buffer);
    }
    infile.close();

	return outPutList;
}

bool FtpDownloadder::flashLocalCache(const OutPutList& fileList, const string& remotFolderPath,const string& localCacheFolder)
{
	checkFolderExistAndMKDIR(localCacheFolder);
	
	// TODO
	for(auto var : fileList)
	{
		string filePath = remotFolderPath +"/"+ var;
		cout<<filePath<<endl;
		downLoadFile(filePath,localCacheFolder);
	}
	return true;
}

string FtpDownloadder::downLoadFile(const string& filePath,const string& localFolderPath)
{
	checkFolderExistAndMKDIR(localFolderPath);
	string localPath = localFolderPath;
	string t_remotPath;
	char t_filename[255];

	// TODO
	CURL *curl;
	CURLcode res; 
	
	curl_global_init(CURL_GLOBAL_DEFAULT);

	t_remotPath = m_url+"/"+filePath;
	memset(t_filename,0,255);
	auto index = strrchr(filePath.c_str(),'/');
	strcpy(t_filename,index+1);

	localPath+=string(t_filename);
	creat(localPath.c_str(),S_IRWXU);

	int use_resume = 0;
	curl_off_t local_file_len = -1 ; 
	struct stat file_info;  

	if(stat(localPath.c_str(), &file_info) == 0)  
	{  
		local_file_len = file_info.st_size;   
		use_resume = 1;  
	}  

	struct FtpFile ftpfile=
	{
		localPath, /* name to store the file as if successful */ 
		NULL
	};
	// cout<< "ftpfile.local: "<<ftpfile.local<<endl;

	curl = curl_easy_init();
	if(curl) 
	{
		curl_easy_setopt(curl, CURLOPT_URL, t_remotPath.c_str());        
		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_RESUME_FROM_LARGE, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
		res = curl_easy_perform(curl);  
		curl_easy_cleanup(curl);
	}

	curl_global_cleanup();

	return localPath;
}

std::shared_ptr<FtpDownloadder> createFtpPtr(const char *ip,const char *port,const char *username,const char *password){
	return std::shared_ptr<FtpDownloadder>(new FtpDownloadder(ip,port,username,password));
}

main.cpp测试

#include "download.hpp"
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
    auto dl=createFtpPtr("127.0.0.1","21","wangr","root");
	int SW = argc>1?*argv[1] - '0' : 0;
	//	/home/用户名/qt_demo
	string remotFolderPath = "qt_demo";
	//	/home/用户名/somewhere/qt_demo
	// string remotFolderPath = "somewhere/qt_demo";

	switch (SW)
	{
	case 0: dl->getAllItem(remotFolderPath);
		break;
		//	/home/用户名/u/48205129.png 
	case 1: dl->downLoadFile("u/48205129.png","/home/wangr/d/");
	//	/home/用户名/somewhere/A/48205129.png 
	// case 1: dl->downLoadFile("somewhere/A/48205129.png","/home/wangr/d/");
		break;
	case 2: dl->flashLocalCache(dl->getAllItem(remotFolderPath),remotFolderPath,"/home/wangr/d/");
		break;
	default:
		break;
	}   

	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值