• 售前

  • 售后

热门帖子
入门百科

PHP5.0~5.6 各版本兼容性cURL文件上传功能实例分析

[复制链接]
卡扎菲遇本拉遇h 显示全部楼层 发表于 2021-10-25 19:54:20 |阅读模式 打印 上一主题 下一主题
本文实例分析了PHP5.0~5.6 各版本兼容性cURL文件上传功能。分享给各人供各人参考,具体如下:
近来做的一个需求,要通过PHP调用cURL,以multipart/form-data格式上传文件。踩坑多少,够一篇文章了。
重要告诫
没事不要读PHP的官方中文文档!版本跟不上坑死你!
差别版本PHP之间cURL的区别
PHP的cURL支持通过给
  1. CURL_POSTFIELDS
复制代码
传递关联数组(而不是字符串)来天生
  1. multipart/form-data
复制代码
的POST哀求。
传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与下令行直接调用cURL程序的语法是划一的:
  1. curl_setopt(ch, CURLOPT_POSTFIELDS, array(
  2.   'file' => '@'.realpath('image.png'),
  3. ));
复制代码
equals
  1. $ curl -F "file=@/absolute/path/to/image.png" <url>
复制代码
但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细界说MIME类型、文件名等大概出现在multipart/form-data数据中的附加信息。PHP保举使用CURLFile替换旧的
  1. @
复制代码
语法:
  1. curl_setopt(ch, CURLOPT_POSTFIELDS, [
  2.   'file' => new CURLFile(realpath('image.png')),
  3. ]);
复制代码
PHP 5.5别的引入了
  1. CURL_SAFE_UPLOAD
复制代码
选项,可以逼迫PHP的cURL模块拒绝旧的
  1. @
复制代码
语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。
但是坑的一点在于:
  1. @
复制代码
语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the
  1. @filename
复制代码
API for file uploading is deprecated. Please use the CURLFile class instead)。
对于PHP 5.6+而言,手动设置
  1. CURL_SAFE_UPLOAD
复制代码
为false是毫偶然义的。根本不是字面意义明白的“设置成false,就能开启旧的unsafe的方式”——旧的方式已经作为废弃语法彻底不存在了。PHP 5.6+ == CURLFile only,不要有任何的理想。
我的部署环境是5.4(仅@语法),但开发环境是5.6(仅CURLFile)。都没有压在5.5这个两者都支持过渡版本上,效果就是必须写出带有环境判定的两套代码。
现在问题来了……
环境判定:小心邪术数字!
我见过这种环境判定的代码:
  1. if (version_compare(phpversion(), '5.4.0') >= 0)
复制代码
我对这种代码的评价只有一个字:屎。
这个判定掉入了典型的邪术数字陷阱。版本号莫名其妙的出现在代码之中,不查半天PHP手册和更新汗青,很难懂白作者被卡在了哪个功能的变动上。
代码应该回归本源。我们的实际需求实在是:有CURLFile就优先采用,没有再退化到传统
  1. @
复制代码
语法。那么代码就来了:
  1. if (class_exists('\CURLFile')) {
  2.   $field = array('fieldname' => new \CURLFile(realpath($filepath)));
  3. } else {
  4.   $field = array('fieldname' => '@' . realpath($filepath));
  5. }
复制代码
建议明确指定的退化选项
从可靠的角度,保举指定
  1. CURL_SAFE_UPLOAD
复制代码
的值,明确告知php是容忍还是克制旧的
  1. @
复制代码
语法。留意在低版本PHP中
  1. CURLOPT_SAFE_UPLOAD
复制代码
常量自己大概不存在,需要判定:
  1. if (class_exists('\CURLFile')) {
  2.   curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
  3. } else {
  4.   if (defined('CURLOPT_SAFE_UPLOAD')) {
  5.     curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
  6.   }
  7. }
复制代码
cURL选项设置的序次
不管是
  1. curl_setopt()
复制代码
单发还是
  1. curl_setopt_array()
复制代码
批量,cURL的选项总是设置一个见效一个,而设置好的选项立即就会影响cURL在设置后续选项时的行为。
比方
  1. CURLOPT_SAFE_UPLOAD
复制代码
就和
  1. CURLOPT_POSTFIELDS
复制代码
的行为有关。如果先设置
  1. CURLOPT_POSTFIELDS
复制代码
再设置
  1. CURLOPT_SAFE_UPLOAD
复制代码
,那么后者的束缚作用就不会见效。因为设置前者时cURL就已经把数据实际的识读处置处罚完毕了!
cURL有那么几个选项存在这种坑,务必小心。还好这种存在“依靠关系”的选项不多,机制也不复杂,简单处置处罚即可。我的方法是先批量设置全部的选项,然后直到
  1. curl_exec()
复制代码
的前一刻才用
  1. curl_setopt()
复制代码
单发设置
  1. CURLOPT_POSTFIELDS
复制代码

实际上在
  1. curl_setopt_array()
复制代码
用的数组中,包管
  1. CURLOPT_POSTFIELDS
复制代码
的位置在后边也是可靠的。PHP的关联数组是有序次保障的,我们也可以假设
  1. curl_setopt_array()
复制代码
内部的执行序次肯定是重新到尾按序次(好吧我知道assume不是件功德,不过有些实在太过浅显的事实,就容我下个最低限度的断言吧),以是尽可放心。
我的做法只是在代码表现上加个多余的保险,突出夸大序次的重要性防以后手贱。
定名空间
PHP 5.2或以下的版本没有定名空间。代码中用到了空间分隔符
  1. \
复制代码
就会引发分析器错误。要照顾PHP 5.2实在容易想,放弃定名空间即可。
要留意的反倒是有定名空间的PHP 5.3+。无论是调用CURLFile还是用
  1. class_exists()
复制代码
判定CURLFile的存在性,都保举写成
  1. \CURLFile
复制代码
明确指定顶层空间,防止代码包裹在定名空间内的时候崩掉。
更多关于PHP相干内容感兴趣的读者可检察本站专题:《php curl用法总结》、《PHP网络编程本领总结》、《PHP数组(Array)操作本领大全》、《php字符串(string)用法总结》、《PHP数据结构与算法教程》、《php程序设计算法总结》及《PHP运算与运算符用法总结》
希望本文所述对各人PHP程序设计有所资助。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作