zoukankan      html  css  js  c++  java
  • libcurl编程学习

    一、curl简介

    curl是一个利用URL语法在命令行方式下工作的文件传输工具。它支持的协议有:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。curl同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务器, cookies, 用户名/密码认证, 下载文件断点续传, 上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器, 通过http代理服务器上传文件到FTP服务器等等,功能十分强大。

    二、curl安装

    ubuntu安装:sudo apt-get install curl

    libcurl静态库:./configure & make & install

    windows:下载curl.exe,cmd进入curl.exe所在目录可以直接使用

    三、curl使用

    curl的用法为:curl [options] [URL...],其中options是下载需要的参数,大约有80多个,curl的各个功能完全是依靠这些参数完成的。这里只介绍几种简单的用法,详细的curl的参数在http://curl.haxx.se/docs/说明。

    1、读取网页

      curl http://www.linuxidc.com

    2、保存网页、下载文件

      以page.html命名下载网页:curl –o page.html http://www.linuxidc.com

      以服务器上的文件名命名网页:curl –O http://cgi2.tky.3web.ne.jp/~zzh/screen1.JPG

      批量下载文件:curl -O http://cgi2.tky.3web.ne.jp/~zzh/screen[1-10].JPG

    3、使用代理服务器及其端口

      curl –x 127.0.0.1:8580 –o page.html http://www.linuxidc.com

    4、使用cookie来记录session信息

      cookie 信息存到cookie1.txt中:curl –o page.html –D cookie1.txt http://www.linuxidc.com

    使用上次的cookie并生成新的cookie:curl –o page.html –D cookie2.txt  -b cookie2.txt http://www.linuxidc.com

    5、断点续传

      比如下载screen1.JPG中,突然掉线了,可以这样开始续传:curl -c -O http://cgi2.tky.3wb.ne.jp/~zzh/screen1.JPG

    另外可以用-r选项进行分块下载

    6、上传文件

      比如我们向ftp传一个文件:curl -T localfile -u name:passwd ftp://upload_site:port/path/

      PS:对于ftp服务器用-u name:passwd选项

    7、http提交一个表单GET与POST模式

      GET模式什么option都不用,只需要把变量写在url里面就可以了比如:

        $curl http://www.linuxidc.com/login.cgi?user=nickwolfe&password=12345

      POST模式的选项是 -d

        比如:curl -d "user=nickwolfe&password=12345" http://www.linuxidc.com/login.cgi

    四、curl编程

    1curl编程流程

      LibCurl编程流程在基于LibCurl的程序里,主要采用callback function (回调函数)的形式完成传输任务,用户在启动传输前设置好各类参数和回调函数,当满足条件时libcurl将调用用户的回调函数实现特定功能。下面是利用libcurl完成传输任务的流程:

    (1)调用curl_global_init()初始化libcurl

    (2)调用 curl_easy_init()函数得到 easy interface型指针

    (3)调用curl_easy_setopt设置传输选项

    (4)根据curl_easy_setopt设置的传输选项,实现回调函数以完成用户特定任务

    (5)调用curl_easy_perform()函数完成传输任务

    (6)调用curl_easy_cleanup()释放内存

    在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。

    2、重要函数

    (1)CURLcode curl_global_init(long flags);

    描述:

      这个函数只能用一次。(其实在调用curl_global_cleanup 函数后仍然可再用)

    如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动完成。

    参数:flags

      CURL_GLOBAL_ALL                        //初始化所有的可能的调用。

      CURL_GLOBAL_SSL                       //初始化支持 安全套接字层。

      CURL_GLOBAL_WIN32                  //初始化win32套接字库。

      CURL_GLOBAL_NOTHING              //没有额外的初始化。

    (2)void curl_global_cleanup(void);

      描述:在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。

    (3)char *curl_version( );

      描述: 打印当前libcurl库的版本。

    (4)CURL *curl_easy_init( );

      描述:curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup函数清理.

      一般curl_easy_init意味着一个会话的开始. 它的返回值一般都用在easy系列的函数中.

    (5)void curl_easy_cleanup(CURL *handle);

    描述:

      这个调用用来结束一个会话.与curl_easy_init配合着用.

    参数:

      CURL类型的指针.

    (6)CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

      描述: 这个函数最重要了.几乎所有的curl 程序都要频繁的使用它.它告诉curl库.程序将有如何的行为. 比如要查看一个网页的html代码等.(这个函数有些像ioctl函数)参数:

      1 CURL类型的指针

      2 各种CURLoption类型的选项.(都在curl.h库里有定义,man 也可以查看到)

      3 parameter 这个参数 既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.

      CURLoption 这个参数的取值很多.具体的可以查看man手册.

    (7) CURLcode curl_easy_perform(CURL *handle);描述:这个函数在初始化CURL类型的指针 以及curl_easy_setopt完成后调用. 就像字面的意思所说perform就像是个舞台.让我们设置的

    option 运作起来.参数:

    CURL类型的指针.

    3curl_easy_setopt函数介绍

    本节主要介绍curl_easy_setopt中跟http相关的参数。注意本节的阐述都是以libcurl作为主体,其它为客体来阐述的。

    1. CURLOPT_URL

    设置访问URL

    2. CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA

    回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream); 函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函数中的stream指针的来源。

    3. CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA

    回调函数原型为 size_t function( void *ptr, size_t size,size_t nmemb, void *stream); libcurl一旦接收到http 头部数据后将调用该函数。CURLOPT_WRITEDATA 传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION 函数的stream指针的来源。

    4. CURLOPT_READFUNCTION CURLOPT_READDATA

    libCurl需要读取数据传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数,函数原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源。

    5. CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA

    跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调用,CURLOPT_NOPROGRESS必须被设置为false,CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的第一个参数

    6. CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:

    CURLOPT_TIMEOUT 由于设置传输时间,CURLOPT_CONNECTIONTIMEOUT 设置连接等待时间

    7. CURLOPT_FOLLOWLOCATION

    设置重定位URL

    CURLOPT_RANGE: CURLOPT_RESUME_FROM:

    断点续传相关设置。CURLOPT_RANGE 指定char *参数传递给libcurl,用于指明http域的RANGE头域,例如:

    表示头500个字节:bytes=0-499

    表示第二个500字节:bytes=500-999

    表示最后500个字节:bytes=-500

    表示500字节以后的范围:bytes=500-

    第一个和最后一个字节:bytes=0-0,-1

    同时指定几个范围:bytes=500-600,601-999

    CURLOPT_RESUME_FROM 传递一个long参数给libcurl,指定你希望开始传递的

    偏移量。

    4curl_easy_perform 函数说明(error 状态码)

    该函数完成curl_easy_setopt指定的所有选项,本节重点介绍curl_easy_perform的返回值。返回0意味一切ok,非0代表错误发生。主要错误码说明:

    1.    CURLE_OK

        任务完成一切都好

    2     CURLE_UNSUPPORTED_PROTOCOL

        不支持的协议,由URL的头部指定

    3     CURLE_COULDNT_CONNECT

        不能连接到remote 主机或者代理

    4     CURLE_REMOTE_ACCESS_DENIED

        访问被拒绝

    5     CURLE_HTTP_RETURNED_ERROR

        Http返回错误

    6     CURLE_READ_ERROR

    读本地文件错误

    五、curl编程例子

    1、获取html网页

     1  
     2 #include <stdio.h>  
     3 #include <curl/curl.h>    
     4 #include <stdlib.h>   
     5 int main(int argc, char *argv[])   
     6 {  
     7     CURL *curl;             //定义CURL类型的指针   
     8     CURLcode res;           //定义CURLcode类型的变量,保存返回状态码  
     9     if(argc!=2)  
    10     {  
    11         printf("Usage : file <url>;/n");  
    12         exit(1);  
    13     }  
    14     curl = curl_easy_init();        //初始化一个CURL类型的指针  
    15     if(curl!=NULL)  
    16    {   
    17 // 设置curl选项. 其中CURLOPT_URL是让用户指定url. argv[1]中存放的命令行传进来的网址  
    18         curl_easy_setopt(curl, CURLOPT_URL, argv[1]);         
    19         //调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这里只在屏幕上显示出来.  
    20         res = curl_easy_perform(curl);    
    21         //清除curl操作.    
    22         curl_easy_cleanup(curl);    
    23     }    
    24     return 0;    
    25 }  
    26 编译:
    27 #gcc  get_http.c  -o get_http –lcurl
    28 #./get_http www.baidu.com

    2网页下载保存

     1 // 采用CURLOPT_WRITEFUNCTION 实现网页下载保存功能  
     2   
     3 #include <stdio.h>;  
     4   
     5 #include <stdlib.h>;  
     6   
     7 #include <unistd.h>;  
     8   
     9 #include <curl/curl.h>;  
    10   
    11 #include <curl/types.h>;  
    12   
    13 #include <curl/easy.h>;  
    14   
    15 FILE *fp;  // 定义FILE类型指针  
    16   
    17 //这个函数是为了符合 CURLOPT_WRITEFUNCTION而构造的  
    18   
    19 //完成数据保存功能  
    20   
    21 size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)   
    22   
    23 {  
    24   
    25     int written = fwrite(ptr, size, nmemb, (FILE *)fp);  
    26   
    27     return written;  
    28   
    29 }  
    30   
    31 int main(int argc, char *argv[])  
    32   
    33 {  
    34   
    35     CURL *curl;  
    36   
    37     curl_global_init(CURL_GLOBAL_ALL);   
    38   
    39     curl=curl_easy_init();  
    40   
    41     curl_easy_setopt(curl, CURLOPT_URL, argv[1]);   
    42   
    43     if((fp=fopen(argv[2],"w"))==NULL)  
    44   
    45     {  
    46   
    47         curl_easy_cleanup(curl);  
    48   
    49         exit(1);  
    50   
    51     }  
    52   
    53 ////CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理  
    54   
    55     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);   
    56   
    57     curl_easy_perform(curl);  
    58   
    59     curl_easy_cleanup(curl);  
    60   
    61     exit(0);  
    62   
    63 }  
    64  
    65 
    66 编译:
    67 #gcc  save_http.c  -o save_http –lcurl
    68 #./save_http www.baidu.com  /tmp/baidu

    3、进度条实例(显示文件下载进度)

      1 // 采用CURLOPT_NOPROGRESS, CURLOPT_PROGRESSFUNCTION    CURLOPT_PROGRESSDATA 实现文件传输进度提示功能  
      2   
      3 //函数采用了gtk库,故编译时需指定gtk库  
      4   
      5 //函数启动专门的线程用于显示gtk 进度条bar  
      6   
      7 #include <stdio.h>  
      8 #include <gtk/gtk.h>   
      9 #include <curl/curl.h>   
     10 #include <curl/types.h> /* new for v7 */   
     11 #include <curl/easy.h> /* new for v7 */  
     12   
     13 GtkWidget *Bar;  
     14   
     15 ////这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的  
     16   
     17 //完成数据保存功能  
     18   
     19 size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)   
     20 {    
     21    return fwrite(ptr, size, nmemb, stream);    
     22 }  
     23   
     24 // 这个函数是为了符合CURLOPT_READFUNCTION而构造的  
     25   
     26 // 数据上传时使用  
     27   
     28 size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)   
     29 {    
     30   return fread(ptr, size, nmemb, stream);    
     31 }  
     32   
     33 // 这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的  
     34   
     35 //显示文件传输进度,t代表文件大小,d代表传输已经完成部分  
     36   
     37 int my_progress_func(GtkWidget *bar,  
     38   
     39                      double t, /* dltotal */    
     40                      double d, /* dlnow */    
     41                      double ultotal,    
     42                      double ulnow)   
     43 {  
     44   /*  printf("%d / %d (%g %%)/n", d, t, d*100.0/t);*/    
     45   gdk_threads_enter();   
     46   gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);   
     47   gdk_threads_leave();   
     48   return 0;  
     49 }  
     50 
     51 void *my_thread(void *ptr)   
     52 {   
     53   CURL *curl;    
     54   CURLcode res;    
     55   FILE *outfile;    
     56   gchar *url = ptr;   
     57   curl = curl_easy_init();   
     58   if(curl)    
     59   {    
     60     outfile = fopen("test.curl", "w");   
     61     curl_easy_setopt(curl, CURLOPT_URL, url);  
     62     curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);   
     63     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);   
     64     curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);   
     65     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);   
     66     curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);   
     67     curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar);   
     68     res = curl_easy_perform(curl);    
     69     fclose(outfile);  
     70     /* always cleanup */    
     71     curl_easy_cleanup(curl);  
     72   }    
     73   return NULL;   
     74 }  
     75   
     76 int main(int argc, char **argv)    
     77 {  
     78   
     79   GtkWidget *Window, *Frame, *Frame2;  
     80   
     81   GtkAdjustment *adj;  
     82   
     83   /* Must initialize libcurl before any threads are started */  
     84   
     85   curl_global_init(CURL_GLOBAL_ALL);  
     86   
     87   /* Init thread */  
     88   
     89   g_thread_init(NULL);  
     90   
     91   gtk_init(&argc, &argv);  
     92   
     93   Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);  
     94   
     95   Frame = gtk_frame_new(NULL);  
     96   
     97   gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT);  
     98   
     99   gtk_container_add(GTK_CONTAINER(Window), Frame);  
    100   
    101   Frame2 = gtk_frame_new(NULL);  
    102   
    103   gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN);  
    104   
    105   gtk_container_add(GTK_CONTAINER(Frame), Frame2);  
    106   
    107   gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5);  
    108   
    109   adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);  
    110   
    111   Bar = gtk_progress_bar_new_with_adjustment(adj);  
    112   
    113   gtk_container_add(GTK_CONTAINER(Frame2), Bar);  
    114   
    115   gtk_widget_show_all(Window);  
    116   
    117   if (!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)  
    118   
    119     g_warning("can't create the thread");  
    120   
    121   gdk_threads_enter();  
    122   
    123   gtk_main();  
    124   
    125   gdk_threads_leave();  
    126   
    127   return 0;  
    128   
    129 }  
    130  
    131 
    132 编译:
    133 #export PKG_CONFIG_PATH=/usr/lib/pkgconfig/ 
    134 #gcc progress.c –o progress ` pkg-config --libs –cflags gtk+-2..0` -lcurl –lgthread-2.0
    135 #./ progress  http://software.sky-union.cn/index.asp

    4断点续传实例

    [cpp] view plaincopyprint?
     
      1  
      2 //采用CURLOPT_RESUME_FROM_LARGE 实现文件断点续传功能  
      3   
      4 #include <stdlib.h>  
      5   
      6 #include <stdio.h>  
      7   
      8 #include <sys/stat.h>  
      9   
     10 #include <curl/curl.h>  
     11   
     12 //这个函数为CURLOPT_HEADERFUNCTION参数构造  
     13   
     14 /* 从http头部获取文件size*/  
     15   
     16 size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) {  
     17   
     18        int r;  
     19   
     20        long len = 0;  
     21   
     22        /* _snscanf() is Win32 specific */  
     23   
     24        // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld/n", &len);  
     25   
     26  r = sscanf(ptr, "Content-Length: %ld/n", &len);  
     27   
     28        if (r) /* Microsoft: we don't read the specs */  
     29   
     30               *((long *) stream) = len;  
     31   
     32        return size * nmemb;  
     33   
     34 }  
     35   
     36 /* 保存下载文件 */  
     37   
     38 size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)  
     39   
     40 {  
     41   
     42         return fwrite(ptr, size, nmemb, stream);  
     43   
     44 }  
     45   
     46 /* 读取上传文件 */  
     47   
     48 size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)  
     49   
     50 {  
     51   
     52        FILE *f = stream;  
     53   
     54        size_t n;  
     55   
     56        if (ferror(f))  
     57   
     58               return CURL_READFUNC_ABORT;  
     59   
     60        n = fread(ptr, size, nmemb, f) * size;  
     61   
     62        return n;  
     63   
     64 }  
     65   
     66 // 下载 或者上传文件函数  
     67   
     68 int download(CURL *curlhandle, const char * remotepath, const char * localpath,  
     69   
     70            long timeout, long tries)  
     71   
     72 {  
     73   
     74        FILE *f;  
     75   
     76        curl_off_t local_file_len = -1 ;  
     77   
     78        long filesize =0 ;  
     79   
     80        CURLcode r = CURLE_GOT_NOTHING;  
     81   
     82        int c;  
     83   
     84   struct stat file_info;  
     85   
     86   int use_resume = 0;  
     87   
     88   /* 得到本地文件大小 */  
     89   
     90   //if(access(localpath,F_OK) ==0)  
     91   
     92     if(stat(localpath, &file_info) == 0)  
     93   
     94      {  
     95   
     96         local_file_len =  file_info.st_size;  
     97   
     98         use_resume  = 1;  
     99   
    100       }  
    101   
    102   //采用追加方式打开文件,便于实现文件断点续传工作  
    103   
    104        f = fopen(localpath, "ab+");  
    105   
    106        if (f == NULL) {  
    107   
    108               perror(NULL);  
    109   
    110               return 0;  
    111   
    112        }  
    113   
    114        //curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);  
    115   
    116        curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);  
    117   
    118               curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);  // 设置连接超时,单位秒  
    119   
    120        //设置http 头部处理函数  
    121   
    122        curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);  
    123   
    124        curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);  
    125   
    126  // 设置文件续传的位置给libcurl  
    127   
    128        curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);  
    129   
    130        curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);  
    131   
    132        curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);  
    133   
    134        //curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);  
    135   
    136        //curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);  
    137   
    138        curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L);  
    139   
    140        curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);  
    141   
    142          r = curl_easy_perform(curlhandle);  
    143   
    144        fclose(f);  
    145   
    146        if (r == CURLE_OK)  
    147   
    148               return 1;  
    149   
    150        else {  
    151   
    152               fprintf(stderr, "%s/n", curl_easy_strerror(r));  
    153   
    154               return 0;  
    155   
    156        }  
    157   
    158 }  
    159   
    160 int main(int c, char **argv) {  
    161   
    162        CURL *curlhandle = NULL;  
    163   
    164        curl_global_init(CURL_GLOBAL_ALL);  
    165   
    166        curlhandle = curl_easy_init();  
    167   
    168        //download(curlhandle, "ftp://user:pass@host/path/file", "C://file", 0, 3);  
    169   
    170   download(curlhandle , "http://software.sky-union.cn/index.asp","/work/index.asp",1,3);  
    171   
    172        curl_easy_cleanup(curlhandle);  
    173   
    174        curl_global_cleanup();  
    175   
    176        return 0;  
    177   
    178 }  
    179  
    180 编译:
    181 #gcc  resume.c  -o resume –lcurl
    182 #./ resume

    以上仅供入门学习,后续有待研究。。。

    1. //采用CURLOPT_RESUME_FROM_LARGE 实现文件断点续传功能  
    2.   
    3. #include <stdlib.h>  
    4.   
    5. #include <stdio.h>  
    6.   
    7. #include <sys/stat.h>  
    8.   
    9. #include <curl/curl.h>  
    10.   
    11. //这个函数为CURLOPT_HEADERFUNCTION参数构造  
    12.   
    13. /* 从http头部获取文件size*/  
    14.   
    15. size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) {  
    16.   
    17.        int r;  
    18.   
    19.        long len = 0;  
    20.   
    21.        /* _snscanf() is Win32 specific */  
    22.   
    23.        // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld/n", &len);  
    24.   
    25.  r = sscanf(ptr, "Content-Length: %ld/n", &len);  
    26.   
    27.        if (r) /* Microsoft: we don't read the specs */  
    28.   
    29.               *((long *) stream) = len;  
    30.   
    31.        return size * nmemb;  
    32.   
    33. }  
    34.   
    35. /* 保存下载文件 */  
    36.   
    37. size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)  
    38.   
    39. {  
    40.   
    41.         return fwrite(ptr, size, nmemb, stream);  
    42.   
    43. }  
    44.   
    45. /* 读取上传文件 */  
    46.   
    47. size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)  
    48.   
    49. {  
    50.   
    51.        FILE *f = stream;  
    52.   
    53.        size_t n;  
    54.   
    55.        if (ferror(f))  
    56.   
    57.               return CURL_READFUNC_ABORT;  
    58.   
    59.        n = fread(ptr, size, nmemb, f) * size;  
    60.   
    61.        return n;  
    62.   
    63. }  
    64.   
    65. // 下载 或者上传文件函数  
    66.   
    67. int download(CURL *curlhandle, const char * remotepath, const char * localpath,  
    68.   
    69.            long timeout, long tries)  
    70.   
    71. {  
    72.   
    73.        FILE *f;  
    74.   
    75.        curl_off_t local_file_len = -1 ;  
    76.   
    77.        long filesize =0 ;  
    78.   
    79.        CURLcode r = CURLE_GOT_NOTHING;  
    80.   
    81.        int c;  
    82.   
    83.   struct stat file_info;  
    84.   
    85.   int use_resume = 0;  
    86.   
    87.   /* 得到本地文件大小 */  
    88.   
    89.   //if(access(localpath,F_OK) ==0)  
    90.   
    91.     if(stat(localpath, &file_info) == 0)  
    92.   
    93.      {  
    94.   
    95.         local_file_len =  file_info.st_size;  
    96.   
    97.         use_resume  = 1;  
    98.   
    99.       }  
    100.   
    101.   //采用追加方式打开文件,便于实现文件断点续传工作  
    102.   
    103.        f = fopen(localpath, "ab+");  
    104.   
    105.        if (f == NULL) {  
    106.   
    107.               perror(NULL);  
    108.   
    109.               return 0;  
    110.   
    111.        }  
    112.   
    113.        //curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);  
    114.   
    115.        curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);  
    116.   
    117.               curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);  // 设置连接超时,单位秒  
    118.   
    119.        //设置http 头部处理函数  
    120.   
    121.        curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);  
    122.   
    123.        curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);  
    124.   
    125.  // 设置文件续传的位置给libcurl  
    126.   
    127.        curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);  
    128.   
    129.        curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);  
    130.   
    131.        curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);  
    132.   
    133.        //curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);  
    134.   
    135.        //curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);  
    136.   
    137.        curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L);  
    138.   
    139.        curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);  
    140.   
    141.          r = curl_easy_perform(curlhandle);  
    142.   
    143.        fclose(f);  
    144.   
    145.        if (r == CURLE_OK)  
    146.   
    147.               return 1;  
    148.   
    149.        else {  
    150.   
    151.               fprintf(stderr, "%s/n", curl_easy_strerror(r));  
    152.   
    153.               return 0;  
    154.   
    155.        }  
    156.   
    157. }  
    158.   
    159. int main(int c, char **argv) {  
    160.   
    161.        CURL *curlhandle = NULL;  
    162.   
    163.        curl_global_init(CURL_GLOBAL_ALL);  
    164.   
    165.        curlhandle = curl_easy_init();  
    166.   
    167.        //download(curlhandle, "ftp://user:pass@host/path/file", "C://file", 0, 3);  
    168.   
    169.   download(curlhandle , "http://software.sky-union.cn/index.asp","/work/index.asp",1,3);  
    170.   
    171.        curl_easy_cleanup(curlhandle);  
    172.   
    173.        curl_global_cleanup();  
    174.   
    175.        return 0;  
    176.   
    177. }  

    编译gcc  resume.c  -o resume –lcurl

    ./ resume

  • 相关阅读:
    AcWing 157. 树形地铁系统 (hash判断树同构)打卡
    AcWing 156. 矩阵 (哈希二维转一维查询)打卡
    AcWing 144. 最长异或值路径 01字典树打卡
    AcWing 143. 最大异或对 01字典树打卡
    AcWing 142. 前缀统计 字典树打卡
    AcWing 139. 回文子串的最大长度 hash打卡
    AcWing 138. 兔子与兔子 hash打卡
    常用C库函数功能及用法
    编程实现C库函数
    C语言面试题5
  • 原文地址:https://www.cnblogs.com/foundwant/p/3195166.html
Copyright © 2011-2022 走看看