研究报告指出的目标是使用libcurl实现ftp文件上传和下载功能
一、Libcurlde简要
Libcurl的而且易于使用的利用url进行文件传输的库。
, libcurl当前支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP,LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP协议。libcurl相同支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传。代理。cookies,和用户认证。
Libcurl是一个轻量级的库,编译后可以执行到多种平台,包含:Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64,Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX,OpenVMS, RISC OS, Novell NetWare, DOS 等
二、libcurl的接口
Libcurl分为简单和复杂的接口。
简单的接口是一个同步的,高效的,高速的。这样的借口主要用于文件传输。
大量的应用程序都使用这样的方式。而复杂的姐姐偶是一个异步的,在这里不做过多研究
三、libcurl简单的接口工作流程
1、使用libcurl中的curl_easy_init()来初始化一个简单的文件传输会话而且获取到一个handle
2、通过使用curl_easy_setopt()来设置全部的选项參数。在这些參数中最重要的就是URL,同一时候你也极有可能须要设置一些回调函数。这些回调函数将会在条件符合的情况下被调用。
3、当上面的工作都做完了的时候。就能够使用curl_easy_perform()通知libcurl进行文件传输了。该函数在整个传输过程完毕或者失败的时候才会返回一个值。
4、当你运行了第3步之后,你能够使用curl_easy_getinfo()来获取传输的信息
5、最后,你相同能够使用curl_easy_cleanup()来结束本次文件会话
以下针对这五个步骤,编写一个实例进行測试
四、部分功能函数的介绍
1、CURL *curl_easy_init( );
该函数必须首先调用,将会返回一个CURL*类型的handle.而且该函数将会和curl_easy_cleanup()一起配合使用。增加初始化出错的话,该函数将会返回一个NULL。
2、void curl_easy_cleanup(CURL *handle)
该函数一定是最后被调用的,他的參数应该是curl_easy_init的返回值;
3、CURLcode curl_easy_setopt(CURL*handle, CURLoption option, parameter);
该函数从名字上看就知道是设置一些參数的。通过设置不同的參数,将会改变libcurl的功能作用。这个须要细致阅读指导文档,一旦设置方式不恰当,导致的错误将是致命的。
具体參数的使用方式在这个网址上描写叙述的非常具体
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
4、CURLcode curl_easy_perform(CURL * easy_handle);
像我们刚才提到的那样,这个函数应该是在init和setopt之后使用的,这个函数一旦运行,将会通知libcurl运行我们之前设置的全部方法,值得注意的是,当一个handle被增加到一个multi handle中之后,该參数handle将不能被函数perform调用
五、实例演示
1、以下来看一个简单的实例:
#include<stdio.h> #include<curl/curl.h> int main(int argc,char** argv) { CURL *pCurlHandle = NULL; CURLcode errorCode = 0; /*1. 初始化一个pCurlHandle*/ pCurlHandle = curl_easy_init(); if( pCurlHandle ) { /*2. 设置pCurlHandle的URL*/ curl_easy_setopt( pCurlHandle,CURLOPT_URL, "http://blog.csdn.net/jxnu_xiaobing" ); /*3. 由于上述网址已被重定向了。所以设置为CURLOPT_FOLLOWLOCATION*/ curl_easy_setopt( pCurlHandle,CURLOPT_FOLLOWLOCATION, 1L ); /*4. 開始运行上述opt*/ errorCode = curl_easy_perform(pCurlHandle ); if( errorCode != CURLE_OK ) { printf("curl_easy_perform() failed "); } } else { printf(" curl_easy_init() failed "); } /*5. 最后关闭pCurlHandle*/ curl_easy_cleanup( pCurlHandle ); return 0; }
2、上述的样例比較简单就是一个訪问网页的样例。以下继续学习一个ftp上传的样例
#include<stdio.h> #include<string.h> #include<curl/curl.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<errno.h> #include<unistd.h> #defineLOCAL_FILE "/tmp/xiaobing.txt" #defineREMOTE_URL "ftp://172.30.26.247:21/xiaobing.txt" static size_tread_callback(void *ptr, size_t size, size_t nmemb, void *stream) { curl_off_t nread; /* in real-world cases, this would probablyget this data differently as this fread() stuff is exactly what thelibrary already would do by default internally */ size_t retcode = fread(ptr, size, nmemb,(FILE*)stream); nread = (curl_off_t)retcode; fprintf(stderr, "*** We read %"CURL_FORMAT_CURL_OFF_T " bytes from file ",nread); return retcode; } int main(int argc,char **argv) { CURL *pCurlhandle; CURLcode res; FILE *hd_src; struct stat file_info; curl_off_t fsize; /*1. 获取待上传文件的大小 */ if(stat(LOCAL_FILE, &file_info)) { printf("Couldnt open '%s': %s ",LOCAL_FILE, strerror(errno)); return 1; } fsize = (curl_off_t)file_info.st_size; printf("Local file size: %"CURL_FORMAT_CURL_OFF_T " bytes. ", fsize); /*2. 获取待上传文件的描写叙述符 */ hd_src = fopen(LOCAL_FILE, "rb"); /*3. 初始化全部可能的调用*/ curl_global_init(CURL_GLOBAL_ALL); /*4. 创建一个curlhandle*/ pCurlhandle = curl_easy_init(); if(curl) { /*5.设置一个回调函数 */ curl_easy_setopt(pCurlhandle, CURLOPT_READFUNCTION, read_callback); /*6.使能上传标志位 */ curl_easy_setopt(pCurlhandle, CURLOPT_UPLOAD, 1L); /*7.指定ftpserver的url */ curl_easy_setopt(pCurlhandle,CURLOPT_URL, REMOTE_URL); /*8.指定须要上传的文件 */ curl_easy_setopt(pCurlhandle, CURLOPT_READDATA, hd_src); /*9.设置待上传文件的大小,这个大小是上面获取到的注意:当參数 为CURLOPT_INFILESIZE_LARGE的时候。size类型应该是curl_off_t的, 当參数为CURLOPT_INFILESIZE的时候size应该是long类型的*/ curl_easy_setopt(pCurlhandle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize); /*10. 開始运行我们上述设定的方法*/ res= curl_easy_perform(pCurlhandle); /*11. 检查是否运行成功 */ if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s ", curl_easy_strerror(res)); /*12. 关闭pCurlhandle*/ curl_easy_cleanup(pCurlhandle); } fclose(hd_src); /* close the local file */ /*13. 清除全部可能的调用*/ curl_global_cleanup(); return 0; }
上述程序就行实现ftp上传文件
3、最后来看一个tfp下载的实例:
/************************************************************************************* * * 文件名称: TfpcurlDownload.c * * 功能: curl測试程序 * * 作者: http://blog.csdn.net/King_BingGe * * 创建时间: 2014年09月29号 * * 最后改动时间: 2014年09月29号 * * 具体: 无 * **************************************************************************************/ #include <stdio.h> #include <string.h> #include <curl/curl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #define REMOTE_URL "ftp://172.30.26.247:21/xiao.txt" typedef struct Ftpfile { const char *filename; FILE *stream; }Cftpfile; static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *stream) { Cftpfile *out = (Cftpfile*)stream; if( out && !out->stream ) { out->stream = fopen(out->filename, "wb"); if(!out->stream) { printf("write_callback failed "); return -1; } } return fwrite(ptr, size, nmemb, out->stream); } int main(int argc, char **argv) { CURL *pCurlhandle; CURLcode res; curl_off_t fsize; Cftpfile ftpfile = { "/tmp/xiaoxiao.txt" , NULL }; /*3. 初始化全部可能的调用*/ curl_global_init(CURL_GLOBAL_ALL); /*4. 创建一个curlhandle*/ pCurlhandle = curl_easy_init(); if(pCurlhandle) { /*5. 设置一个回调函数 */ curl_easy_setopt(pCurlhandle, CURLOPT_WRITEFUNCTION, write_callback ); /*7. 指定ftpserver的url */ curl_easy_setopt(pCurlhandle,CURLOPT_URL, REMOTE_URL); /*8. 指定须要上传的文件 */ curl_easy_setopt(pCurlhandle, CURLOPT_USERPWD, "cdn_ftp:123456"); /*9. 指定须要上传的文件 */ curl_easy_setopt(pCurlhandle, CURLOPT_WRITEDATA, &ftpfile ); /*10. 设置待下载文件的大小。这个大小是上面获取到的注意:当參数 为CURLOPT_INFILESIZE_LARGE的时候,size类型应该是curl_off_t的。 当參数为CURLOPT_INFILESIZE的时候size应该是long类型的*/ curl_easy_setopt(pCurlhandle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize); /*11. 開始运行我们上述设定的方法 */ res = curl_easy_perform(pCurlhandle); /*12. 检查是否运行成功 */ if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s ", curl_easy_strerror(res)); /*13. 关闭pCurlhandle*/ curl_easy_cleanup(pCurlhandle); } else { printf("curl_easy_init failed "); } /*14. 清除所有可能的呼叫*/ curl_global_cleanup(); return 0; }