curl实现ftp客户端 ftp上送内存数据实例

30.1 前言

ftpclient相对于ftpsever在应用实现上比较简单,可以调用现成的很多库快速实现ftp、http等客户端,本篇将实现使用curl 实现ftp客户端的实例编程。

本篇博客整合了ftp上送文件以及上送内存数据的方式,便于理解和使用,用户只需填写对应的结构数据,并将该参数传入对应的函数,便可实现ftp上送文件或ftp上送内存数据功能。模块的编写是基于模块独立的设计思想,与用户代码实现尽可能的隔离开来,降低耦合。

 

30.2 代码实例

main.c

#ifndef __FTPCLIENT_H  
#define __FTPCLIENT_H      
  
#ifdef __cplusplus   
extern "C" {   
#endif  
/***************************************************************** 
* 宏定义 
******************************************************************/  
#define FTP_OPERATION_UPLOAD_MEM            0   //上传内存数据  
#define FTP_OPERATION_UPLOAD_FILE           1   //上传文件数据  
  
/***************************************************************** 
* 结构、枚举定义 
******************************************************************/  
typedef struct _stFtpUserInfo  
{  
    int nOperation;             //操作选择  
    int nHaveSendLen;           //已发送长度  
    int nSedSize;               //发送数据大小  
    int nRcvBufLen;             //缓冲区长度  
    int nRcvSize;               //接收body数据大小  
  
    char cSndFilePathName[128]; //上送文件路径名  
    char *pRcvBuffer;           //指向用户用来存储数据的buf  
    char *pSendBuffer;          //指向用户发送数据的buf  
}stFtpUserInfo;  
  
typedef struct _stFtpClientInfo  
{  
    int nServerPort;            //ftp服务器监听端口号  
    char chServerIP[32];        //ftp服务器IP  
    char chServerPath[128];     //ftp服务器文件路径  
    char chUserName[32];        //ftp服务器登录用户  
    char chUserPassWord[32];    //ftp服务器登录密码  
  
    int use_proxy;              //是否使用http服务器代理  
    int nHttpServerPort;        //ftp服务器监听端口号  
    char chHttpServerIP[32];    //ftp服务器IP  
    char chHttpServerPath[64];//ftp服务器文件路径  
  
    stFtpUserInfo stFtpUser;  
}stFtpClientInfo;  
  
int ftpClient_ftpUpload(stFtpClientInfo *pstUserArg,long *pRespCode);  
  
#ifdef __cplusplus  
}  
#endif  
  
#endif  

ftpClient.c

#ifdef __cplusplus  
    extern "C" {  
#endif  
      
  
/***************************************************************** 
* 包含头文件 
******************************************************************/  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include "curl.h"  
#include "ftpClient.h"  
  
  
/************************************************* 
** Function:ftpClient_writeCallBack 
** Description:ftp回调数据接收函数 
** Input:无 
** Output: 
 
** Return:-1-失败 0-成功 
** Author: 
** Date:2018-11-27 
 
** Modification History: 
** Author: 
** Date: 
** Description: 
*************************************************/  
size_t ftpClient_writeCallBack(void *ptr, size_t size, size_t nmemb, void *stream)  
{  
    int writeLength = 0;  
    int written  = size*nmemb;  
    stFtpUserInfo *pSt = (stFtpUserInfo*)stream;      
  
    if(0)//此处记录body内容  
    {  
        if(pSt->pRcvBuffer != NULL)  
        {  
            writeLength = (written <= (pSt->nRcvBufLen - pSt->nRcvSize))?(written):(pSt->nRcvBufLen - pSt->nRcvSize);  
            memcpy((char*)(pSt->pRcvBuffer) +pSt->nRcvSize, ptr, writeLength);  
            pSt->nRcvSize += writeLength;  
            //printf("%d line,nWRLength=%d written=%d nUsedLength=%d writeLength=%d\n",__LINE__,pSt->nRcvBufLen, written,pSt->nRcvSize,writeLength);  
        }  
        return writeLength;  
    }  
    if(0){  
        printf("\n %s\n", ptr);  
    }  
    return 0;  
}  
  
/************************************************* 
** Function:ftpClient_file2Ftp 
** Description:ftp读取文件并上送 
** Input:无 
** Output: 
 
** Return:-1-失败 0-成功 
** Author: 
** Date:2018-11-27 
 
** Modification History: 
** Author: 
** Date: 
** Description: 
*************************************************/  
size_t ftpClient_file2Ftp(void *ptr, size_t size, size_t nmemb, void *stream)  
{  
    size_t retcode = fread(ptr, size, nmemb, stream);  
    return retcode;  
}  
  
  
/************************************************* 
** Function:ftpClient_mem2Ftp 
** Description:ftp读取内存数据 
** Input:无 
** Output: 
 
** Return:-1-失败 0-成功 
** Author: 
** Date:2018-11-27 
 
** Modification History: 
** Author: 
** Date: 
** Description: 
*************************************************/  
size_t ftpClient_mem2Ftp(void *ptr, size_t size, size_t nmemb, void *stream)  
{  
    size_t cpoyLength = 0;  
    size_t copySize  = size*nmemb;  
    stFtpUserInfo *pSt = (stFtpUserInfo*)stream;  
      
    if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {  
        return 0;  
    }  
      
    if(pSt->pSendBuffer != NULL)  
    {  
        cpoyLength = (copySize <= (pSt->nSedSize - pSt->nHaveSendLen))?(copySize):(pSt->nSedSize - pSt->nHaveSendLen);  
        memcpy(ptr,(char*)(pSt->pSendBuffer) +pSt->nHaveSendLen, cpoyLength);  
        pSt->nHaveSendLen += cpoyLength;  
        //printf("%d line,copySize=%d nSedSize=%d nHaveSendLen=%d cpoyLength=%d\n",__LINE__,copySize, pSt->nSedSize,pSt->nHaveSendLen,cpoyLength);  
    }  
    return cpoyLength;  
}  
  
  
/************************************************* 
** Function:ftpClient_ftpUpload 
** Description:ftpUpload 
** Input:无 
** Output: 
 
** Return:-1-失败 0-成功 
** Author: 
** Date:2018-11-27 
 
** Modification History: 
** Author: 
** Date: 
** Description: 
*************************************************/  
int ftpClient_ftpUpload(stFtpClientInfo *pstUserArg,long *pRespCode)  
{  
    int nRet = 0;  
    long response_code      = -1;  
    char chftpUrl[160]  ={0};  
    char chHttpUrl[128]     ={0};  
  
    FILE *ffp = NULL;  
    curl_off_t fsize = 0;  
  
    CURL *curl = NULL;  
    CURLcode code = 0;  
    struct stat file_info;  
    struct curl_slist *chunk = NULL;      
  
    *pRespCode = 0;  
  
    if(NULL == pstUserArg){  
        printf("%s func Invalid parameter at (%d) line\n",__FUNCTION__,__LINE__);  
        return -1;  
    }  
  
    curl = curl_easy_init();  
    if(curl)  
    {  
        snprintf(chftpUrl,160,"ftp://%s:%u/%s", pstUserArg->chServerIP, pstUserArg->nServerPort, pstUserArg->chServerPath);      
          
    //  printf("%s func User=%s ,passwd=%s,chUrl=%s at (%d) line\n",__FUNCTION__,pstUserArg->chUserName,pstUserArg->chUserPassWord,chftpUrl,__LINE__);  

  		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 
        curl_easy_setopt(curl, CURLOPT_URL, chftpUrl);  
        curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //上传  
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);   //注意,毫秒超时一定要设置这个  
        curl_easy_setopt(curl, CURLOPT_USERNAME, pstUserArg->chUserName);  
        curl_easy_setopt(curl, CURLOPT_PASSWORD, pstUserArg->chUserPassWord);          
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L);    //设置延时1s  
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60L);  
        curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1);//创建不存在的目录  
          
        /* enable TCP keep-alive for this transfer */  
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);  
        /* keep-alive idle time to 120 seconds */  
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 600L);  
        /* interval time between keep-alive probes: 60 seconds */  
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);  
  
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ftpClient_writeCallBack);  
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pstUserArg->stFtpUser);   /*接收响应*/  
  
        switch(pstUserArg->stFtpUser.nOperation)  
        {  
            case FTP_OPERATION_UPLOAD_MEM:  //发送内存数据  
                curl_easy_setopt (curl, CURLOPT_READDATA, &pstUserArg->stFtpUser);                 
                curl_easy_setopt (curl, CURLOPT_READFUNCTION, ftpClient_mem2Ftp);  
                curl_easy_setopt (curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) pstUserArg->stFtpUser.nSedSize);  
                break;  
            case FTP_OPERATION_UPLOAD_FILE:  //ftp发送文件  
  
                /********************打开文件***************/  
                if(stat(pstUserArg->stFtpUser.cSndFilePathName, &file_info)){  
                    printf("ftp upload stat %s failed\n", pstUserArg->stFtpUser.cSndFilePathName);  
                    goto iExit;  
                }  
                fsize = (curl_off_t) file_info.st_size;  
                ffp = fopen (pstUserArg->stFtpUser.cSndFilePathName, "rb");  
                if(NULL == ffp){  
                    printf("ftp fopen %s failed!\n", pstUserArg->stFtpUser.cSndFilePathName);  
                    goto iExit;  
                }  
  
                curl_easy_setopt (curl, CURLOPT_READDATA, ffp);               
                curl_easy_setopt (curl, CURLOPT_READFUNCTION, ftpClient_file2Ftp);  
                curl_easy_setopt (curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) fsize);  
                break;  
            default:  
                break;  
        }  
  
        /*是否使用了http代理服务器*/  
        if(pstUserArg->use_proxy == 1)  
        {  
            snprintf(chHttpUrl,128,"http://%s/%s/%s", pstUserArg->chHttpServerIP, pstUserArg->nHttpServerPort, pstUserArg->chHttpServerPath);  
            curl_easy_setopt (curl, CURLOPT_PROXY, chHttpUrl);  
        }  
  
        code = curl_easy_perform(curl);  
        if(code != CURLE_OK)  
        {  
            nRet = -1;  
            printf("%s func curl_easy_perform failed:%s at (%d) line\n",__FUNCTION__,curl_easy_strerror(code),__LINE__);  
        }   
        else  
        {  
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);  
            if(226 != response_code)//对于ftp成功是226码  
            {  
                nRet = -1;  
                printf("%s func curl_easy_getinfo RESPONSE_CODE: %d at (%d) line\n",__FUNCTION__,response_code,__LINE__);  
            }  
        }         
          
        switch(pstUserArg->stFtpUser.nOperation)  
        {  
            case FTP_OPERATION_UPLOAD_MEM:  //发送内存数据  
                break;  
            case FTP_OPERATION_UPLOAD_FILE:  //ftp发送文件  
                if(NULL != ffp) fclose(ffp);  
                break;  
            default:  
                break;  
        }  
  
        curl_slist_free_all(chunk);  
        curl_easy_cleanup(curl);  
          
        *pRespCode = response_code;  
        return nRet;  
    }  
      
    return -1;  
  
iExit:  
    curl_slist_free_all(chunk);  
    curl_easy_cleanup(curl);  
    return -1;  
}  
  
  
#ifdef __cplusplus  
}  
#endif  

main.c

#include <string.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <pthread.h>  
#include <unistd.h>  
#include "ftpClient.h"  
  
int main()  
{  
    int nRet = -1;  
    char *pSendData = "123456789";  
    long lRespCode = 0;  
    stFtpClientInfo stFtpClienter;    
    memset(&stFtpClienter,0,sizeof(stFtpClienter));  
  
    memcpy(stFtpClienter.chServerPath,"/test.jpg",strlen("/test.jpg"));  
    memcpy(stFtpClienter.chServerIP,"192.168.36.56",strlen("192.168.36.56"));  
    memcpy(stFtpClienter.chUserName,"root",strlen("root"));  
    memcpy(stFtpClienter.chUserPassWord,"3214",strlen("3214"));  
    stFtpClienter.nServerPort               = 2125;  
    stFtpClienter.use_proxy                 = 0;//是否选择http代理服务器,0-不选择  
    stFtpClienter.stFtpUser.nOperation      = FTP_OPERATION_UPLOAD_MEM; //选择是否上送内存数据或文件  
    stFtpClienter.stFtpUser.pRcvBuffer      = NULL;  
    stFtpClienter.stFtpUser.nRcvBufLen      = 0;  
    stFtpClienter.stFtpUser.nRcvSize        = 0;          
    stFtpClienter.stFtpUser.nHaveSendLen    = 0;  
    stFtpClienter.stFtpUser.pSendBuffer     = pSendData; //发送数据  
    stFtpClienter.stFtpUser.nSedSize        = strlen(pSendData); //发送数据长度  
      
    /*上送至ftp服务器*/  
    nRet = ftpClient_ftpUpload(&stFtpClienter,&lRespCode);  
    if(nRet<0){  
        printf("ftpClient_ftpUpload failed\n");  
        return -1;  
    }  
  
    return 0;  
} 

猜你喜欢

转载自blog.csdn.net/Chasing_Chasing/article/details/89840041
今日推荐