Realizing FTP single file upload and download with libcurl under linux

Libcurl is a function library that provides data transmission functions. Its main function is to connect different types of servers through different protocols. At present, libcurl mainly supports http, https, ftp, gopher, telnet, dict, file, ldap and other protocols and various SSL security authentication.
In libcurl based programs, the library functions provided by libcurl are used to complete specific tasks. Before starting the transfer task, the developer writes the callback function and sets various parameters. When the conditions are met, libcurl calls the callback function to realize the function task.
Details are available on the libcurl official website: https://curl.haxx.se/libcurl/features.html

1. The general flow of the upload and download function realized by curl library function is as follows:

1.1 curl_global_init();		/* initialization */		
1.2 curl_easy_init();		/* Get curl operator */ 
1.3 curl_easy_setopt();		/* Configure the operation parameters of the response to the curl operator*/
1.4 curl_easy_perform();	/* Run curl operator*/ 
1.5 curl_easy_cleanup();	/* Free curl resources */ 
1.6 curl_global_cleanup();	/* Free all curl resources */

2. Introduction to main functions

2.1 CURLcode curl_global_init(long falgs);
This function calls curl in the program_ global_ Previously, the cleanup function can only be used once, namely curl_global_init and curl_ global_ Use with cleanup function. Call curl_ global_ Curl must be called when init is not used_ global_ Cleanup frees resources. If this function is in curl_ easy_ The init function is not called when it is called, and it will be automatically completed by the libcurl library. The parameters required for this function are as follows:

  CURL_GLOBAL_ALL		//: initialize all possible calls
  CURL_GLOBAL_SSL		//: initializes calls that support secure sockets
  CURL_GLOBAL_WIN32	//: initialize WIN32 socket library
  CURL_GLOBAL_NOTHING	//: no additional initialization requirements

2.2.CURL* curl_easy_init();
This function returns a curl type pointer after calling. Subsequent curl operations (FTP and http operations) are configured and implemented based on the curl pointer. Curl needs to be used after the call of curl pointer_ easy_ The cleanup function to free up resources.

2.3CURLcode curl_easy_setopt(CURL* handle,CURLoption option,parameter);
Used to tell curl library what behavior the program needs the library to do. CURL* handle is the operator, namely curl above_ easy_ Init function returns the generated curl pointer. Curloption represents various options. option parameter can be a pointer to a function, an object, or a long variable What it uses depends on the second parameter

2.4.CURLcode curl_easy_perform(CURL* handle);
Set curl_ easy_ After the setopt works, the function is called to run the session. CURL* handle is the operator.

2.5.void curl_easy_cleanup(CURLhandle);
Used to end a libcurl session with curl_easy_init. CURL handle is the operator

2.6.void curl_global_cleanup(void);
Use this function to end all libcurl usage, similar to the close() function.

For a detailed understanding of all functions in the libcur library, please refer to the libcurl official website:
https://curl.haxx.se/libcurl/c/

3.curl upload and download code implementation
This code is the FTP client code. It solves how to install libcurl Library under linux (shell instruction installation or github download source code installation) and FTP server construction by itself.
Note: the ftp server is set to anonymous mode, so the user name and password are not configured

3.1 related header files

#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>
#include <sys/stat.h>

3.2 FTP upload single file code

/* read data to upload */
static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
    size_t n;
    FILE *f = (FILE*)stream;
    if (ferror(f))
    {
        return CURL_READFUNC_ABORT;
    }
        
    n = fread(ptr, size, nmemb, f) * size;
    return n;
}

/***********************************************************
** function:ftp_upload
** descripte: Use libcurl to upload a file from ftp client
** parameter: 
	** crlpath_file: ftp server address and file name to be uploaded
	** localpath_file: File name to be uploaded locally
	** timeout: Upload timeout 0: disable
** return:  0:Success - 1: failed	
***********************************************************/
int ftp_upload(const char * crlpath_file, const char * localpath_file, long timeout)
{
    FILE *fd;
    CURL *curlup = NULL;
    struct stat file_info;
    curl_off_t fsize;

    if(stat(localpath_file, &file_info))    /* Gets the size of the uploaded file */ 
    {
        printf("ftp file couldn't open '%s': %s\n", localpath_file, strerror(errno));
        return -1;
    }
    fsize = (curl_off_t)file_info.st_size;
    
    fd = fopen(localpath_file, "rb");
    if (fd == NULL) 
    {
       	printf("ftp fopen file failed");
        return -1;
    }

    curl_global_init(CURL_GLOBAL_ALL);
    curlup = curl_easy_init();
    if(curlup == NULL)
    {
        printf("ftp curl_easy_init create curl failed");
        return -1;
    }

    curl_easy_setopt(curlup, CURLOPT_UPLOAD, 1L);               //Enable upload function
    curl_easy_setopt(curlup, CURLOPT_URL, crlpath_file);        //Set specific goals
//    curl_easy_setopt(curlup, CURLOPT_USERPWD, "ftp:");        //ftp anonymous mode does not need to set user name and password
    curl_easy_setopt(curlup, CURLOPT_READFUNCTION, readfunc);   //Use the Read function provided by curl
    curl_easy_setopt(curlup, CURLOPT_READDATA, fd);             //Pass the parameter fd to the fourth parameter of the callback function readfunc
	curl_easy_setopt(curlup, CURLOPT_VERBOSE, 1L);              //Open the complete protocol / debugging output -- > and output the debugging information to the terminal interface         
    curl_easy_setopt(curlup, CURLOPT_INFILESIZE_LARGE,fsize);	/*Set the size of the file to upload (optional) */ 
    if (timeout)
    {
        curl_easy_setopt(curlup, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
    }       	
	CURLcode r = curl_easy_perform(curlup);
    fclose(fd);
    
    if (r != CURLE_OK)
    {
        printf("ftp upload event %s\n", curl_easy_strerror(r));
        return -1;
    }
   
    curl_easy_cleanup(curlup);
    curl_global_cleanup();  
    return 0;
}

3.3 ftp download single file code

//write data to download
static size_t writefunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
    return fwrite(ptr, size, nmemb, (FILE*)stream);
}

/***********************************************************
** function:ftp_download
** descripte: Use libcurl to download a file from ftp client
** parameter: 
	** crlpath_file: ftp server address and file name to be downloaded
	** localpath_file: Local file name after downloading the file
	** timeout: Download timeout 0: disable
** return:  0:Success - 1: failed	
***********************************************************/
int ftp_download(const char * crlpath_file, const char * localpath_file, long timeout)
{
    FILE *fd;  
    CURL *curldwn = NULL;
	
    fd = fopen(localpath_file, "ab+");	//
    if (fd == NULL)
    {
        printf("ERROR create %s failed", localpath_file);
        return 0;
    }

    curl_global_init(CURL_GLOBAL_ALL);
    curldwn = curl_easy_init();
    if(curldwn == NULL)
    {
        printf("curl_easy_init create curl failed");
        return -1;
    }
    curl_easy_setopt(curldwn, CURLOPT_URL, crlpath_file);
    //curl_easy_setopt(curldwn, CURLOPT_USERPWD, "ftp:");        //ftp anonymous mode does not need to set user name and password
    curl_easy_setopt(curldwn, CURLOPT_WRITEFUNCTION, writefunc);
    curl_easy_setopt(curldwn, CURLOPT_WRITEDATA, fd);		    //Pass the parameter fd to the fourth parameter of the callback function writefunc
    curl_easy_setopt(curldwn, CURLOPT_VERBOSE, 1L);			    //Open the complete protocol / debugging output -- > and output the debugging information to the terminal interface
    if(timeout > 0)
    {
        curl_easy_setopt(curldwn, CURLOPT_CONNECTTIMEOUT, timeout);    //Connection timeout setting
    }
    CURLcode r = curl_easy_perform(curldwn);
    fclose(fd);
    
    if (r != CURLE_OK)
    {
        printf("download event %s\n", curl_easy_strerror(r));
        curl_easy_cleanup(curldwn);
        curl_global_cleanup();
        return -1;
    }
    
    printf("ftp client download file successful");
    curl_easy_cleanup(curldwn);
    curl_global_cleanup();
    return 0;
}

4. Examples

int main(int c, char **argv) 
{
	/*
		192.168.0.185:Change the address to the ftp server address (the same LAN as the client)	
		ftp://192.168.0.185/uploadfile.txt: The file uploaded to the ftp server is named UploadFile txt
		/home/user/uploadfile.txt: ftp Files to be uploaded by the client
	*/
    ftp_upload("ftp://192.168.0.185/uploadfile.txt", "/home/user/uploadfile.txt", 0);
    
    	/*
		ftp://192.168.0.185/downloadfile.txt: Download the downloadfile.ftp server Txt file
		/home/user/downloadfile.txt: ftp The client named the downloaded file downloadfile Txt and store it in the / home/user / directory
	*/
    ftp_download("ftp://192.168.0.185/downloadfile.txt", "/home/user/downloadfile.txt", 0);
	
	while(1)
	{
		sleep(1);
	}
    return 0;
}

reference resources: https://blog.csdn.net/wangqingchuan92/article/details/80221041

Keywords: Linux

Added by Q on Mon, 17 Jan 2022 15:13:55 +0200