比 file_get_contents() 更优的 cURL 详解(附实例)
PHP 可以使用 file_get_content() 函数抓取网页内容,但却无法进行更复杂的处理,譬如文件的上传或下载、 Cookie 操作等等。而 cURL 提供了这些功能。
一、cURL简介
在 PHP 中,cURL 是一个扩展库。它可以与各种类型的服务器、使用各种类型的协议进行连接和通讯。
它目前支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 协议,同时也支持 HTTPS 认证、HTTP POST、 FTP 上传、代理、cookies 和 用户名 + 密码的认证等。
二、cURL函数库
常用函数
| 函数 | 描述 |
| curl_init() | 初始化 cURL 会话 |
| curl_setopt() | 设置 cURL 选项 |
| curl_exec() | 执行 cURL 会话 |
| curl_getinfo() | 获取当前会话信息 |
| curl_errno() | 返回最后一次的错误代码 |
| curl_error() | 返回当前会话最后一次的错误字符串 |
| curl_close() | 关闭 cURL 会话 |
其他函数
| 函数 | 描述 |
| curl_copy_handle() | 复制一个 cURL 句柄和它的所有选项。 |
| curl_escape() | 返回转义字符串,对给定的字符串进行URL编码。 |
| curl_file_create() | 创建一个 CURLFile 对象。 |
| curl_multi_add_handle() | 向 cURL 批处理会话中添加单独的curl句柄。 |
| curl_multi_close() | 关闭一组 cURL 句柄。 |
| curl_multi_exec() | 运行当前 cURL 句柄的子连接。 |
| curl_multi_getcontent() | 如果设置了 CURLOPT_RETURNTRANSFER ,则返回获取的输出的文本流。 |
| curl_multi_info_read() | 获取当前解析的 cURL 的相关传输信息。 |
| curl_multi_init() | 返回一个新 cURL 批处理句柄。 |
| curl_multi_remove_handle() | 移除 cURL 批处理句柄资源中的某个句柄资源。 |
| curl_multi_select() | 等待所有 cURL 批处理中的活动连接。 |
| curl_multi_setopt() | 设置一个批处理 cURL 传输选项。 |
| curl_multi_strerror() | 返回描述错误码的字符串文本。 |
| curl_pause() | 暂停及恢复连接。 |
| curl_reset() | 重置 libcurl 的会话句柄的所有选项。 |
| curl_setopt_array() | 为 cURL 传输会话批量设置选项。 |
| curl_share_close() | 关闭 cURL 共享句柄。 |
| curl_share_init() | 初始化 cURL 共享句柄。 |
| curl_share_setopt() | 设置一个共享句柄的 cURL 传输选项。 |
| curl_strerror() | 返回错误代码的字符串描述。 |
| curl_unescape() | 解码 URL 编码后的字符串。 |
| curl_version() | 获取 cURL 版本信息。 |
三、实现流程
1. 初始化 cURL 会话
2. 设置 cURL 选项
3. 执行 cURL 会话
4. 获取 cURL 信息和(或)错误信息(这一步可以没有)
5. 关闭 cURL 句柄
这里面最复杂的是第 2 步,cURL 的设置选项有很多,下面会结合实例来了解。查看所有选项请看这里:http://www.runoob.com/php/func-curl_setopt.html
四、实例1.GET请求
GET 请求的流程就是 cURL 的一般流程。
在本地服务器 localserver.com 根目录准备一个测试脚本 index.php,内容如下:
<?php
$url = 'http://www.baidu.com'; // 初始化,获得一个cURL句柄
$ch = curl_init(); // 设置选项
curl_setopt($ch, CURLOPT_URL, $url); // 请求URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据流,而不直接输出
curl_setopt($ch, CURLOPT_HEADER, 0); // 无需响应的header头
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); //连接超时,单位为秒 // 执行并获取返回内容
$output = curl_exec($ch);
if($output === false){
$output = 'cURL error: ' . curl_error($ch);
} // 释放 cURL 句柄资源
curl_close($ch); print_r($output);
?>
浏览器访问本地服务器首页 localserver.com/index.php,显示百度首页。
五、实例2.POST请求
POST 请求需要设置两个选项:
curl_setopt($ch, CURLOPT_POST, 1); // 表明POST请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData)); // POST提交数据
先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:
<?php
$input = file_get_contents('php://input');
echo $input;
?>
然后在本地服务器 localserver.com 根目录来写用于 POST 请求的脚本 index.php,内容如下:
<?php
$url = 'http://remoteserver.com/index.php';
$data = array(
'fname'=> 'Daniel',
'lname' => 'Stenberg'
); // 初始化
$ch = curl_init(); // 设置选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1); // POST请求
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); //POST数据。用http_build_query()转换为“&”拼接的字符串 // 执行并获取返回内容
$output = curl_exec($ch);
if($output === false){
$output = 'cURL error: ' . curl_error($ch);
} // 释放 cURL 句柄资源
curl_close($ch); print_r($output);
?>
浏览器访问 localserver.com/index.php,显示如下:
fname=Daniel&lname=Stenberg
六、实例3.上传文件
cURL 上传文件的思路是:在文件路径的前面添加"@"符号,并装在请求字段里实现上传。后台可以通过 $_FILES 获取上传文件信息。但 PHP5.6 以后,废除了"@"符号,可以使用 CURLFile 类实现上传。
先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:
<?php
$action = $_POST['action'];
if($action == 'uploadImage'){
$name = $_FILES['file']['name'];
$tmpname = $_FILES['file']['tmp_name']; // 保存到当前脚本所在目录
move_uploaded_file($tmpname, dirname(__FILE__).'/'.$name); $error = $_FILES['file']['error'];
switch ($error) {
case 0: echo '上传成功'; break;
case 1: echo '文件大小超出 php.ini 限制'; break;
case 2: echo '文件大小超出 表单 MAX_FILE_SIZE 限制'; break;
case 3: echo '文件部分被上传'; break;
case 4: echo '没有文件被上传'; break;
case 6: echo '找不到临时文件夹'; break;
case 7: echo '文件写入失败'; break;
default: $output = '未知错误';
}
}
?>
然后在本地服务器 localserver.com 根目录准备一个图片文件 test.jpg 和 cURL 上传脚本 index.php, 脚本内容如下:
<?php
$url = 'http://remoteserver.com/index.php';
$file = realpath(getcwd() . '/test.jpg');
$data = array(
'action' => 'uploadImage',
'file' => '@' . $file
);
if(version_compare(PHP_VERSION, '5.6.0') > 0){
$data['file'] = new CURLFile($file);
} // 初始化
$ch = curl_init(); // 设置选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 执行并获取返回内容
$output = curl_exec($ch);
if($output === false){
$output = 'cURL error: ' . curl_error($ch);
} // 释放 cURL 句柄资源
curl_close($ch); print_r($output);
?>
浏览器访问 localserver.com/index.php,显示如下:
上传成功
查看远程服务器根目录,发现多了一张刚才上传的图片。
七、实例4.下载文件
cURL 下载文件的一个思路是:设置 cURL 选项 CURLOPT_FILE 为一个文件指针,以此将请求的资源文件关联到一个文件流里,这个文件流一般是 fopen()函数的返回值。使用文件流将远程文件写到本地,可以避免写(下载)大文件时可能的内存出错。
在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:
<?php
$url = 'http://remoteserver.com/test.jpg';
$file = './test.jpg';
$fp = fopen($file, 'w'); // 初始化
$ch = curl_init(); // 设置选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_FILE, $fp); // 用于传输的文件流,默认是STDOUT // 执行并获取返回内容
$output = curl_exec($ch);
if($output === false){
$output = 'cURL error: ' . curl_error($ch);
} // 获取已下载大小
$size_download = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD); // 释放资源
fclose($fp);
curl_close($ch); if ($size_download && $size_download == filesize($file)) {
echo "下载成功";
} else {
echo "下载失败或不完整";
}
?>
浏览器访问 localserver.com/index.php,显示如下:
下载成功
查看本地服务器根目录,发现下载到了远程的图片。
八、实例5.批处理
cURL 有一个批处理句柄,通过打开多个 cURL 句柄,并将这些句柄绑定到一个批处理句柄,然后在循环中依次处理每个 cURL 连接,可以实现异步的批处理,类似“多线程”。
在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:
<?php
$urls = array(
'http://www.baidu.com',
'http://www.qidian.com'
);
$count = count($urls);
$ch = array(); // 创建批处理cURL句柄
$mh = curl_multi_init(); // 初始化每个cURL,并设置选项,绑定给批处理句柄
for ($i = 0; $i < $count; $i++) {
$ch[$i] = curl_init();
curl_setopt($ch[$i], CURLOPT_URL, $urls[$i]);
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch[$i], CURLOPT_HEADER, 0);
curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT, 30);
curl_multi_add_handle($mh, $ch[$i]);
} // 执行批处理
$running = null;
do {
usleep(10000); // 延迟0.01秒,单位为百万分之一秒
curl_multi_exec($mh, $running); // 异步实现批处理,类似“多线程”
} while($running > 0); // 获取每个cURL的响应
$res = array();
for ($i = 0; $i < $count; $i++) {
$res[$i] = curl_multi_getcontent($ch[$i]);
} // 关闭全部句柄
for ($i = 0; $i < $count; $i++) {
curl_multi_remove_handle($mh, $ch[$i]);
}
curl_multi_close($mh); print_r($res);
?>
浏览器访问 localserver.com/index.php,显示了“连在一起”的百度首页和起点网首页。
相关阅读:
参考链接:
比 file_get_contents() 更优的 cURL 详解(附实例)的更多相关文章
- Windows WMIC命令使用详解(附实例)
第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符.在WMIC命令行提示符上,命令以交互的方式执行 执行“wmic”命令启动WMIC命令行环境.这个命令可以在 ...
- [No000013A]Windows WMIC命令使用详解(附实例)
第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符.在WMIC命令行提示符上,命令以交互的方式执行 执行“wmic”命令启动WMIC命令行环境.这个命令可以在 ...
- (转载)Windows WMIC命令使用详解(附实例)
原文地址:http://www.jb51.net/article/49987.htm 第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符.在WMIC命令行提示 ...
- linux wget 命令用法详解(附实例说明)
Linux wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,尤其对于网络管理员,经常要下载一些软件或从远程服务器恢复备份到本地服务器 Linux wget是一个下 ...
- (转)MySQL性能调优my.cnf详解
MySQL性能调优my.cnf详解 https://blog.linuxeye.cn/379.html http://blog.csdn.net/orichisonic/article/details ...
- httpd配置文件详解及实例
httpd配置文件详解及实例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.http协议的组成 http协议是C/S架构:我们可以把浏览器(如:IE,Firefox,Safar ...
- linux管道命令grep命令参数及用法详解---附使用案例|grep
功能说明:查找文件里符合条件的字符串. 语 法:grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>] ...
- Protocol Buffer技术详解(Java实例)
Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...
- Protocol Buffer技术详解(C++实例)
Protocol Buffer技术详解(C++实例) 这篇Blog仍然是以Google的官方文档为主线,代码实例则完全取自于我们正在开发的一个Demo项目,通过前一段时间的尝试,感觉这种结合的方式比较 ...
随机推荐
- Delphi SQL语句字符串拼接
单引号必须成对出现,最外层的单引号表示其内部符号为字符:除最外层以外的单引号,每两个单引号代表一个'字符.加号:+用于字符串之间的连接.字符串常量用四个单引号,例如 ' select * from T ...
- BZOJ 2333 棘手的操作(离线+线段树+带权并查集)
这题搞了我一天啊...拍不出错原来是因为极限数据就RE了啊,竟然返回WA啊.我的线段树要开8倍才能过啊... 首先可以发现除了那个加边操作,其他的操作有点像线段树啊.如果我们把每次询问的联通块都放在一 ...
- 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币 背包dp
题目描述 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币系统中,硬币的面值通常是1,5,10,20或25,50,以及100单位的 ...
- BZOJ4247 挂饰(动态规划)
相当于一个有负体积的背包.显然如果确定了选哪些,应该先把体积小的挂上去.于是按体积从小到大排序,就是一个裸的背包了. #include<iostream> #include<cstd ...
- Python 源码剖析(五)【DICT对象】
五.DICT对象 1.散列表概述 2.PyDictObject 3.PyDictObject的创建与维护 4.PyDictObject 对象缓冲池 5.Hack PyDictObject 这篇篇幅较长 ...
- Andorid API Package ---> android.app
包名: android.app Added in API level 1 URL:http://developer. ...
- Unable to open connection to "Microsoft SQL Server, provider V1.0.5000.0 in framework
解决办法:1 以管理员身份登陆2 找到ORACLE_HOME文件夹(D:\oracle\ora92),点右键,选属性——安全,在组或用户栏中选"Authenticated Users&quo ...
- 【题解】51nod1327 棋盘游戏
那天和机房的同学们一起想了很久,然而并没有做出来……今天看了题解,的确比较巧妙,不过细细想来其实规律还是比较明显,在这里记录一下~ 当天自己做的时候,主要想到的是两点 : 1.按列dp 2.对行进行排 ...
- HDU.1575 Tr A ( 矩阵快速幂)
HDU.1575 Tr A ( 矩阵快速幂) 点我挑战题目 题意分析 直接求矩阵A^K的结果,然后计算正对角线,即左上到右下对角线的和,结果模9973后输出即可. 由于此题矩阵直接给出的,题目比较裸. ...
- bzoj1042: [HAOI2008]硬币购物(DP+容斥)
1600+人过的题排#32还不错嘿嘿 浴谷夏令营讲过的题,居然1A了 预处理出f[i]表示购买价值为i的东西的方案数 然后每次询问进行一次容斥,答案为总方案数-第一种硬币超限方案-第二种超限方案-第三 ...