比 file_get_contents() 更优的 cURL 详解(附实例)「建议收藏」

比 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,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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 请求需要设置两个选项:

1
2
curl_setopt(
$ch
, CURLOPT_POST, 1); 
// 表明POST请求
curl_setopt(
$ch
, CURLOPT_POSTFIELDS, 
$postData
)); 
// POST提交数据

先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:

1
2
3
4
<?php
    
$input 

file_get_contents
(
'php://input'
);
    
echo 
$input
;
?>

然后在本地服务器 localserver.com 根目录来写用于 POST 请求的脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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,显示如下:

1
fname=Daniel&lname=Stenberg

 

六、实例3.上传文件

cURL 上传文件的思路是:在文件路径的前面添加”@”符号,并装在请求字段里实现上传。后台可以通过 $_FILES 获取上传文件信息。但 PHP5.6 以后,废除了”@”符号,可以使用 CURLFile 类实现上传。

先在远程服务器 remoteserver.com 根目录准备一个用于接收的脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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, 脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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,显示如下:

1
上传成功

查看远程服务器根目录,发现多了一张刚才上传的图片。

 

七、实例4.下载文件

cURL 下载文件的一个思路是:设置 cURL 选项 CURLOPT_FILE 为一个文件指针,以此将请求的资源文件关联到一个文件流里,这个文件流一般是 fopen()函数的返回值。使用文件流将远程文件写到本地,可以避免写(下载)大文件时可能的内存出错。

在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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,显示如下:

1
下载成功

查看本地服务器根目录,发现下载到了远程的图片。 

 

八、实例5.批处理

cURL 有一个批处理句柄,通过打开多个 cURL 句柄,并将这些句柄绑定到一个批处理句柄,然后在循环中依次处理每个 cURL 连接,可以实现异步的批处理,类似“多线程”。

在本地服务器 localserver.com 根目录来写测试脚本 index.php,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?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,显示了“连在一起”的百度首页和起点网首页。

转载:https://www.cnblogs.com/mingc/p/7425321.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/112203.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 学成在线源代码(学成网首页代码)

    首先同一目录下放置三个文件夹(imagesxxx.htmlstyle.css)图片:头部区域分四个模块:logo(图片)导航栏(无序列表)搜索(文本输入框、button按钮)用户(图片)<divclass=”headerw”><!–logo部分–><divclass=”logo”><!–alt显示未加载时,所提示的文字,title显示鼠标放上时,所提示的文件

  • 算数平均数、中位数、众数和几何平均数[通俗易懂]

    算数平均数、中位数、众数和几何平均数[通俗易懂]文章目录算数平均数、中位数、众数和几何平均数算数平均数、中位数、众数和几何平均数统计数据时经常用到的几种数的比较:算数平均数中位数众数几何平均数英文名ArithmeticmeanMedianModeGeometricMean别称均值中值定义n个变量的和除以n。中位数是按顺序排列的一组数据中居于中间位置的数,即在这组数据中,有一半的…

  • 软考网络工程师备考经验

    软考网络工程师备考经验软考网工的备考经验文章目录讲废话题型备考经验上午题下午题刷题软件讲废话本人大三,网络工程专业。11月8日考的试,11月18日出的成绩。上午53,下午54,但是成绩还是让我不太满意鸭!!!最开始大二的时候从老师的嘴里听到的有能力的去考软考(其实我也没什么能力,是个老菜逼了。。。)所以下课的时候就了解了一下。软考有初级、中级、高级。初级是网管员没什么技术含量挺简单的,高级呢,要写论文还没项目经验也不会写论文,所以就选择了中级网络工程师。题型分为上午题(75道选择题)、下午题(案例分析4大题7

  • pycharm2021.11.3版本激活-激活码分享

    (pycharm2021.11.3版本激活)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

  • linux安装svn服务器的两种方式

    linux安装svn服务器的两种方式操作环境:CentOS7.264位==============第一种:采用压缩包安装:比如你们公司服务器上安装软件有自己的规定,一般会采用压缩包安装。==============第一步:SVN服务器端压缩包下载下载地址:http://mirrors.cnnic.cn/apache/subversion/ 我下载的是subversion-1.8.19版本,下载好的压缩包置于目录/usr/loc…

  • AvalonDock使用心得「建议收藏」

    AvalonDock使用心得「建议收藏」  桌面程序的应用,不可避免的就会用到大量的布局控件,之前的一个项目也想过去做类似于VisualStudio的那种灵活的布局控件,也就是界面上的控件能够实现拖拽放置、隐藏、窗口化等一系列的操作,但由于开发时间以及需求的原因,没有太严格要求这方面功能的实现,也就只能算是想过一下而已,实际用的时候还是固定布局,但是最近接触到新的项目,需要这方面的应用就不得不自己动手查找和做这样的东西了。  有朋…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号