libcurl使用Word文档下载推荐.docx
- 文档编号:21992727
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:38
- 大小:364.94KB
libcurl使用Word文档下载推荐.docx
《libcurl使用Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《libcurl使用Word文档下载推荐.docx(38页珍藏版)》请在冰豆网上搜索。
16.{
17.static
char
str[10000000];
18.strcpy(str,
“”);
19.//return“<
ahref=\”
20.
21.curl_easy_setopt(curl,
CURLOPT_URL,
filename);
//设置下载地址
22.
23.curl_easy_setopt(curl,
CURLOPT_TIMEOUT,
3);
//设置超时时间
24.
25.curl_easy_setopt(curl,
CURLOPT_WRITEFUNCTION,
write_data);
//设置写数据的函数
26.
27.curl_easy_setopt(curl,
CURLOPT_WRITEDATA,
str);
//设置写数据的变量
28.
29.res
=
curl_easy_perform(curl);
//执行下载
30.
31.str[9999999]
‘\0′;
32.if(CURLE_OK
!
res)
NULL;
//判断是否下载成功
33.
34.return
str;
35.}
36.
37.int
main()
38.{
39.char
url[200];
40.curl
curl_easy_init();
//对curl进行初始化
41.
42.char
*result;
43.while(fgets(url,
200,
stdin)){
44.result
down_file(url);
45.if
(result)
puts(result);
46.else
puts(“GetError!
”);
47.printf(“\nPleaseInputaurl:
48.
49.}
50.curl_easy_cleanup(curl);
//释放curl资源
51.
52.
53.return
54.}
下面是转载的curl详细使用:
curl->
libcurl的手册可以查看
http:
//curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTWRITEDATA
译者:
JGood(
)
译者注:
这是一篇介绍如何使用libcurl的入门教程。
文档不是逐字逐句按原文翻译,而是根据笔者对libcurl的理解,参考原文写成。
文中用到的一些例子,可能不是出自原文,而是笔者在学习过程中,写的一些示例程序(笔者使用的libcurl版本是:
7.19.6)。
出现在这里主要是为了更好的说明libcurl的某些api函数的使用。
许多例子都参考libcurl提供的example代码。
原文example中的提供的示例程序完全使用C语言,而这里笔者提供的例子使用C++语言。
因为能力有限,对于libcurl的某些理解和使用可能有误,欢迎批评指正。
目标
本文档介绍了在应用程序开发过程中,如何正确使用libcurl的基本方式和指导原则。
文档使用C语言来调用libcurl的接口,当然也适用于其他与C语言接近的语言。
文档主要针对使用libcurl来进行开发的人员。
文档所掼的应用程序泛指你写的源代码,这些代码使用了libcurl进行数据传输。
更多关于libcurl的功能和接口信息,可以在相关的主页上查阅。
编译源码
有很多种不同的方式来编译C语言代码。
这里使用UNIX平台下的编译方式。
即使你使用的是其他的操作系统,你仍然可以通过阅读本文档来获取许多有用的信息。
编译
你的编译器必须知道libcurl头文件的位置。
所以在编译的时候,你要设置头文件的包含路径。
可以使用curl-config工具来获取这方面的信息:
$curl-config–cflags
链接
编译完源码(这时的源代码不是指libcurl的源代码,你是你自己写的程序代码)之后,你还必须把目标文件链接成单个可执行文件。
你要链接libcurl库,以及libcurl所依赖的其他库,例如OpenSLL库。
当然可能还需要一些其他的操作系统库。
最后你还要设置一些编译选项,当然可以使用curl-config工具简化操作:
$curl-config–libs
是否使用SSL
定制编译libcurl。
与其他库不同的是,libcurl可以定制编译,根据实际需要是否支持某些特性,如是否支持SSL传输,像HTTPS和FTPS。
如果决定需要支持SSL,必须在编译时正确的设置。
可以使用’curl-config’来判断libcurl库是否支持SSL:
$curl-config–feature
autoconf宏
当你编写配置脚本来检测libcurl及其相应设置时,你可以使用预定义宏。
文档docs/libcurl/libcurl.m4告诉你如何使用这些宏。
跨平台的可移植的代码
libcurl的开发人员花费很大的努力,使libcurl尽可能在大多数平台上正常运行。
全局初始化
应用程序在使用libcurl之前,必须先初始化libcurl。
libcurl只需初始化一次。
可以使用以下语句进行初始化:
curl_global_init();
curl_global_init()接收一个参数,告诉libcurl如何初始化。
参数CURL_GLOBAL_ALL
会使libcurl初始化所有的子模块和一些默认的选项,通常这是一个比较好的默认参数值。
还有两个可选值:
CURL_GLOBAL_WIN32
只能应用于Windows平台。
它告诉libcurl初始化winsock库。
如果winsock库没有正确地初始化,应用程序就不能使用socket。
在应用程序中,只要初始化一次即可。
CURL_GLOBAL_SSL
如果libcurl在编译时被设定支持SSL,那么该参数用于初始化相应的SSL库。
同样,在应用程序中,只要初始化一次即可。
libcurl有默认的保护机制,如果在调用curl_easy_perform时它检测到还没有通过curl_global_init进行初始化,libcurl会根据当前的运行时环境,自动调用全局初始化函数。
但必须清楚的是,让系统自已初始化不是一个好的选择。
当应用程序不再使用libcurl的时候,应该调用curl_global_cleanup来释放相关的资源。
在程序中,应当避免多次调用curl_global_init和curl_global_cleanup。
它们只能被调用一次。
libcurl提供的功能
在运行时根据libcurl支持的特性来进行开发,通常比编译时更好。
可以通过调用curl_version_info函数返回的结构体来获取运行时的具体信息,从而确定当前环境下libcurl支持的一些特性。
下面是笔者在visualstudio2008中调用相关函数获取libcurl版本信息的截图:
使用easyinterface
首先介绍libcurl中被称为easyinterface的api函数,所有这些函数都是有相同的前缀:
curl_easy。
当前版本的libcurl也提供了multiinterface,关于这些接口的详细使用,在下面的章节中会有介绍。
在使用multiinterface之前,你首先应该理解如何使用easyinterface。
要使用easyinterface,首先必须创建一个easyhandle,easyhandle用于执行每次操作。
基本上,每个线程都应该有自己的easyhandle用于数据通信(如果需要的话)。
千万不要在多线程之间共享同一个easyhandle。
下面的函数用于获取一个easyhandle:
CURL*easy_handle=curl_easy_init();
在easyhandle上可以设置属性和操作(action)。
easyhandle就像一个逻辑连接,用于接下来要进行的数据传输。
使用curl_easy_setopt函数可以设置easyhandle的属性和操作,这些属性和操作控制libcurl如何与远程主机进行数据通信。
一旦在easyhandle中设置了相应的属性和操作,它们将一直作用该easyhandle。
也就是说,重复使用easyhanle向远程主机发出请求,先前设置的属性仍然生效。
easyhandle的许多属性使用字符串(以\0结尾的字节数组)来设置。
通过curl_easy_setopt函数设置字符串属性时,libcurl内部会自动拷贝这些字符串,所以在设置完相关属性之后,字符串可以直接被释放掉(如果需要的话)。
easyhandle最基本、最常用的属性是URL。
你应当通过CURLOPT_URL属性提供适当的URL:
curl_easy_setopt(easy_handle,CURLOPT_URL,““);
假设你要获取URL所表示的远程主机上的资源。
你需要写一段程序用来完成数据传输,你可能希望直接保存接收到的数据而不是简单的在输出窗口中打印它们。
所以,你必须首先写一个回调函数用来保存接收到的数据。
回调函数的原型如下:
size_twrite_data(void*buffer,size_tsize,size_tnmemb,void*userp);
可以使用下面的语句来注册回调函数,回调函数将会在接收到数据的时候被调用:
curl_easy_setopt(easy_handle,CURLOPT_WRITEFUNCTION,write_data);
可以给回调函数提供一个自定义参数,libcurl不处理该参数,只是简单的传递:
curl_easy_setopt(easy_handle,CURLOPT_WRITEDATA,&
internal_struct);
如果你没有通过CURLOPT_WRITEFUNCTION属性给easyhandle设置回调函数,libcurl会提供一个默认的回调函数,它只是简单的将接收到的数据打印到标准输出。
你也可以通过CURLOPT_WRITEDATA属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。
下面是一些平台相关的注意点。
在一些平台上,libcurl不能直接操作由应用程序打开的文件。
所以,如果使用默认的回调函数,同时通过CURLOPT_WRITEDATA属性给easyhandle传递一个文件指针,应用程序可能会执行失败。
如果你希望自己的程序能跑在任何系统上,你必须避免出现这种情况。
如果以win32动态连接库的形式来使用libcurl,在设置CURLOPT_WRITEDATA属性时,你必须同时
使用CURLOPT_WRITEFUNCTION来注册回调函数。
否则程序会执行失败(笔者尝试只传递一个打开的文件指针而不显式设置回调函数,程序并没有崩溃。
可能是我使用的方式不正确。
)。
当然,libcurl还支持许多其他的属性,在接下来的篇幅里,你将会逐步地接触到它们。
调用下面的函数,将执行真正的数据通信:
success=curl_easy_perform(easy_handle);
curl_easy_perfrom将连接到远程主机,执行必要的命令,并接收数据。
当接收到数据时,先前设置的回调函数将被调用。
libcurl可能一次只接收到1字节的数据,也可能接收到好几K的数据,libcurl会尽可能多、及时的将数据传递给回调函数。
回调函数返回接收的数据长度。
如果回调函数返回的数据长度与传递给它的长度不一致(即返回长度!
=size*nmemb),libcurl将会终止操作,并返回一个错误代码。
当数据传递结束的时候,curl_easy_perform将返回一个代码表示操作成功或失败。
如果需要获取更多有关通信细节的信息,你可以设置CURLOPT_ERRORBUFFER属性,让libcurl缓存许多可读的错误信息。
easyhandle在完成一次数据通信之后可以被重用。
这里非常建议你重用一个已经存在的easyhandle。
如果在完成数据传输之后,你创建另一个easyhandle来执行其他的数据通信,libcurl在内部会尝试着重用上一次创建的连接。
对于有些协议,下载文件可能包括许多复杂的子过程:
日志记录、设置传输模式、选择当前文件夹,最后下载文件数据。
使用libcurl,你不需要关心这一切,你只需简单地提供一个URL,libcurl会给你做剩余所有的工作。
下面的这个例子演示了如何获取网页源码,将其保存到本地文件,并同时将获取的源码输出到控制台上。
1./**
2.
*
@brieflibcurl接收到数据时的回调函数
3.
*
4.
将接收到的数据保存到本地文件中,同时显示在控制台上。
5.
6.
@param[in]buffer接收到的数据所在缓冲区
7.
@param[in]size数据长度
8.
@param[in]nmemb数据片数量
9.
@param[in/out]用户自定义指针
10.
@return获取的数据长度
11.
*/
12.
13.size_t
process_data(void
*buffer,
*user_p)
14.{
15.
FILE
*fp
(FILE
*)user_p;
16.
return_size
fwrite(buffer,
fp);
17.
cout
*)buffer
endl;
18.
return_size;
19.}
21.int
main(int
argc,
**argv)
22.{
23.
//初始化libcurl
25.
CURLcodereturn_code;
26.
return_code
curl_global_init(CURL_GLOBAL_WIN32);
27.
if
(CURLE_OK
return_code)
28.
{
29.
cerr
"
initlibcurlfailed."
30.
-1;
31.
}
32.
33.
//获取easyhandle
34.
35.
CURL
*easy_handle
36.
(NULL
==
easy_handle)
37.
38.
getaeasyhandlefailed."
39.
curl_global_cleanup();
40.
41.
42.
43.
fopen("
data.html"
ab+"
);
//
44.
45.
//设置easyhandle属性
46.
47.
curl_easy_setopt(easy_handle,
49.
&
process_data);
50.
52.
//执行数据请求
53.
54.
curl_easy_perform(easy_handle);
55.
56.
//释放资源
57.
58.
59.
fclose(fp);
60.
curl_easy_cleanup(easy_handle);
61.
62.
63.
64.}
多线程问题
首先一个基本原则就是:
绝对不应该在线程之间共享同一个libcurlhandle,不管是easyhandle还是multihandle(将在下文中介绍)。
一个线程每次只能使用一个handle。
libcurl是线程安全的,但有两点例外:
信号(signals)和SSL/TLShandler。
信号用于超时失效名字解析(timingoutnameresolves)。
libcurl依赖其他的库来支持SSL/STL,所以用多线程的方式访问HTTPS或FTPS的URL时,应该满足这些库对多线程操作的一些要求。
详细可以参考:
OpenSSL:
//www.openssl.org/docs/crypto/threads.html#DESCRIPTION
GnuTLS:
//www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
NSS:
宣称是多线程安全的。
什么时候libcurl无法正常工作
传输失败总是有原因的。
你可能错误的设置了一些libcurl的属性或者没有正确的理解某些属性的含义,或者是远程主机返回一些无法被正确解析的内容。
这里有一个黄金法则来处理这些问题:
将CURLOPT_VERBOSE属性设置为1,libcurl会输出通信过程中的一些细节。
如果使用的是http协议,请求头/响应头也会被输出。
将CURLOPT_HEADER设为1,这些头信息将出现在消息的内容中。
当然不可否认的是,libcurl还存在bug。
当你在使用libcurl的过程中发现bug时,希望能够提交给我们,好让我们能够修复这些bug。
你在提交bug时,请同时提供详细的信息:
通过CURLOPT_VERBOSE属性跟踪到的协议信息、libcurl版本、libcurl的客户代码、操作系统名称、版本、编译器名称、版本等等。
如果你对相关的协议了解越多,在使用libcurl时,就越不容易犯错。
上传数据到远程站点
libcurl提供协议无关的方式进行数据传输。
所以上传一个文件到FTP服务器,跟向HTTP服务器提交一个PUT请求的操作方式是类似的:
1.创建easyhandle或者重用先前创建的easyhandle。
2.设置CURLOPT_URL属性。
3.编写回调函数。
在执行上传的时候,libcurl通过回调函数读取要上传的数据。
(如果要从远程服务器下载数据,可以通过回调来保存接收到的数据。
)回调函数的原型如下:
size_tfunction(char*bufptr,size_tsize,size_tnitems,void*userp);
bufptr指针表示缓冲区,用于保存要上传的数据,size*nitems是缓冲区数据的长度,userp是一个用户自定义指针,libcurl不对该指针作任何操作,它只是简单的传递该指针。
可以使用该指针在应用程序与libcurl之间传递信息。
4.注册回调函数,设置自定义指针。
语法如下:
//注册回调函数
curl_easy_setopt(easy_handle,CURLOPT_READFUNCTION,read_function);
//设置自定义指针
curl_easy_setopt(easy_handle,CURLOPT_READDATA,&
filedata);
5.告诉libcurl,执行的是上传操作。
curl_easy_setopt(easy_handle,CURLOPT_UPLOAD,1L);
有些协议在没有预先知道上传文件大小的情况下,可能无法正确判断上传是否结束,所以最好预先使用CURLOPT_INFILESIZE_LARGE属性:
告诉它要上传文件的大小:
/*inthisexample,file_sizemustbeancurl_off_tvariable*/
curl_easy_setopt(easy_handle,CURLOPT_INFILESIZE_LARGE,file_size);
6.调用curl_easy_perform。
接下来,libcurl将会完成剩下的所有工作。
在上传文件过程中,libcurl会不断调用先前设置的回调函数,用于将要上传的数据读入到缓冲区,并执行上传。
下面的例子演示如何将文件上传到FTP服务器。
笔者使用的是IIS自带的FTP服务,同时在FTP上设置了可写权限。
@brief读取数据的回调。
4.size_t
read_data(void
5.{
fread(buffer,
*)user_p);
7.}
8.
9.int
10.{
13.
CURLcodecode;
14.
code
(code
CURLE_OK)
19.
21.
fopen(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- libcurl 使用