关于cURL上传普通文件操作这里不再详细叙述,Google上大把抓,但这里讲下需要注意的几个点。
1、在对CURLOPT_POSTFIELDS参数进行配置时,注意需要上传文件字段路径头部添加@符号表名该字段是文件
2、@后面要跟文件的绝对路径,例如 array( ‘mypic’=>”@/htdoc/images/pic.jpg” ),当然也可以使用realpath(‘./pic.jpg’) 直接取得文件真是路径
3、请记得将CURLOPT_POST设置为true,此时CURL会做像常规POST表单一样文件HTTP头进行处理 application/x-www-form-urlencoded
下面回归正题,我们在用CURL上传图片的时候,是否和上传普通文件方式一致?
思考一下:我们写程序在做上传图片时,对文件做过什么处理?肯定会有对图片格式/图片MIME 的检测。
案例1、
curl_upload.php 代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 | $data = array( 'uid' => 10086, 'pic' => '@'.realpath('./mypic.png') ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://localhost/server_upload.php' ); curl_setopt($ch, CURLOPT_POST, true ); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $return_data = curl_exec($ch); curl_close($ch); echo $return_data; |
server_upload.php 代码如下
1 2 3 | print_r($_POST); echo "\n_______________________\n"; print_r($_FILES); |
你能想象到当执行 curl_upload.php 会返回什么结果吗?(试着想一下~~) 执行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Array ( [uid] => 10086 ) _______________________ Array ( [pic] => Array ( [name] => mypic.png [type] => application/octet-stream //很明显这不是我想要的 [tmp_name] => C:\Windows\Temp\phpFF32.tmp [error] => 0 [size] => 5903 ) ) |
这样的上传方式显然无法通过文件类型的检测
值得庆幸的是PHP 中CURL CURLOPT_POSTFIELDS 参数支持自定义文件类型
摘录PHP手册
CURLOPT_POSTFIELDS | The full data to post in a HTTP “POST” operation. To post a file, prepend a filename with@ and use the full path. The filetype can be explicitly specified by following the filename with the type in the format ‘;type=mimetype‘. This parameter can either be passed as a urlencoded string like ‘para1=val1¶2=val2&…‘ or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data. As of PHP 5.2.0, value must be an array if files are passed to this option with the @ prefix. As of PHP 5.5.0, the @ prefix is deprecated and files can be sent using CURLFile. |
注意红色部分,大致意思是说:可以显示的按照上传文件格式进行设置文件类型
使用方式(还是上面的例子),我将$data改写如下格式
1 2 3 4 | $data = array( 'uid' => 10086, 'pic' => '@'.realpath('./mypic.png').';type=image/png' ); |
重新执行 curl_upload.php 结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Array ( [uid] => 10086 ) _______________________ Array ( [pic] => Array ( [name] => mypic.png [type] => image/png //此时文件类型已被成功设置 [tmp_name] => C:\Windows\Temp\phpF1E1.tmp [error] => 0 [size] => 5903 ) ) |
关于cURL此种方式其他参考资料:
http://kazymjir.com/blog/curlfile-object-curl_file_create-php/
(上面这篇文章巧妙的使用了 finfo( FILEINFO_MIME )) 和 curl_file_create( ) 在未知MIME情况下动态处理文件MIME信息。
http://curl.haxx.se/mail/curlphp-2007-12/0033.html (cURL官方资料)
http://stackoverflow.com/questions/11468999/how-can-i-modify-content-type-of-uploaded-file-in-php
http://stackoverflow.com/questions/13071747/php-curl-multipart-form-data-with-application-octet-stream-for-a-blank-file?rq=1
看似问题已经解决?
不过在实际应用中,请注意您所使用的cURL以及PHP 的版本。
版本支持情况参考资料:http://blog.csdn.net/cschmin/article/details/6417346
拓展一下:使用PHP内置Soket fsockopen也可以进行上传文件指定类型,当然这不是本次重点。
有话要说