Re: PHP cURL实现模拟登录与采集使用方法详解教程
所属分类:PHP工具与代码
  十、模拟上传文件
(一)基于本地文件上传

在PHP手册的curl_setopt函数中,关于CURLOPT_POSTFIELDS有如下描述:

全部数据使用HTTP协议中的"POST"操作来发送。要发送文件,在文件名前面加上@前缀并使用完整路径。这个参数可以通过urlencoded后的字符串类似'para1=val1&para2=val2&...'或使用一个以字段名为键值,字段数据为值的数组。如果value是一个数组,Content-Type头将会被设置成multipart/form-data。

对于上传文件,这句话包含两个信息:
1. 要上传文件,post的数据参数必须使用数组,使得Content-Type头将会被设置成multipart/form-data。
2. 要上传文件,在文件名前面加上@前缀并使用完整路径。
注意:PHP 5.5.0起,文件上传建议使用CURLFile代替@

因此,模拟文件上传可以按照如下实现:
(1)单文件上传
[code]
//上传D盘下的test.jpg文件,文件必须存在,否则curl处理失败且没有任何提示,Windows下中文文件名上传失败时,可使用iconv('UTF-8', 'GBK//IGNORE', $filename)转码下文件名再上传。
$data = array('name' => 'Foo', 'file' => '@d:/test.jpg');
注: PHP 5.5.0起,文件上传建议使用CURLFile代替@
$ch = curl_init('http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);[/code]

本地测试的时候,在upload.php文件中打印出$_POST和$_FILES即可验证是否上传成功,如下:

[code] print_r($_POST);
print_r($_FILES);[/code]

输出结果类似:

Array ( [name] => Foo ) Array ( [file] => Array ( [name] => test.jpg [type] => application/octet-stream [tmp_name] => D:\xampp\tmp\php2EA0.tmp [error] => 0 [size] => 139999 ) )

(2)多文件上传

[code] // 注: PHP 5.5.0起,文件上传建议使用CURLFile代替@
// 多文件上传
$data = array(
'input_file[0]' => new CURLFile('d:/1.txt', 'text/plain', 'testfile.txt'),
'input_file[1]' => new CURLFile('d:/2.txt', 'text/plain'),
'input_file[2]' => new CURLFile('d:/3.txt', 'text/plain'),
);
$ch = curl_init('http://demo.zjmainstay.cn/php/curl/curlUploadHandler.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);[/code]

输出结果类似:

[code] Array ( [upload_file] => Array ( [name] => Array ( [0] => 1.txt [1] => 2.txt [2] => 3.txt ) [type] => Array ( [0] => text/plain [1] => text/plain [2] => text/plain ) [tmp_name] => Array ( [0] => /tmp/phpkQ75hZ [1] => /tmp/phpuVB5La [2] => /tmp/phpu1z5fm ) [error] => Array ( [0] => 0 [1] => 0 [2] => 0 ) [size] => Array ( [0] => 2 [1] => 2 [2] => 2 ) ) ) [/code]

(3)CURLOPT_POSTFIELDS使用字符串与数组的区别

关于CURLOPT_POSTFIELDS的赋值,另外补充一句描述:

传递一个数组到CURLOPT_POSTFIELDS,cURL会把数据编码成 multipart/form-data,而然传递一个URL-encoded字符串时,数据会被编码成 application/x-www-form-urlencoded。

即:

[code] curl_setopt($ch, CURLOPT_POSTFIELDS, 'param1=val1&param2=val2&...');[/code]

[code] curl_setopt($ch, CURLOPT_POSTFIELDS, array('param1' => 'val1', 'param2' => 'val2', ...));[/code]

相当于html的form表单中:

[code] <form method="post" action="upload.php">
[/code]


[code] <form method="post" action="upload.php" enctype="multipart/form-data">[/code]

的区别。