php curl上传文件返回false,php curl上传文件$_FILES为空的问题

PHP 5.0~5.6 各版本兼容的cURL文件上传

最近做的一个需求,使用PHP cURL上传文件。踩坑若干,整理如下。

不同版本PHP之间cURL的区别

PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。

传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:

1 curl_setopt(ch, CURLOPT_POSTFIELDS, array(

2 'file' => '@'.realpath('image.png'),

3 ));

4 equals

5 $ curl -F "file=@/absolute/path/to/image.png"

但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:

1 curl_setopt(ch, CURLOPT_POSTFIELDS, [

2 'file' => new CURLFile(realpath('image.png')),

3 ]);

PHP 5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。

但是坑的一点在于:

@语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead)。

对于PHP 5.6+而言,手动设置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 if (class_exists('\CURLFile')) {

2 $field = array('fieldname' => new \CURLFile(realpath($filepath)));

3 } else {

4 $field = array('fieldname' => '@' . realpath($filepath));

5 }

建议明确指定的退化选项

从可靠的角度,推荐指定CURL_SAFE_UPLOAD的值,明确告知php是容忍还是禁止旧的@语法。注意在低版本PHP中CURLOPT_SAFE_UPLOAD常量本身可能不存在,需要判断:

69c5a8ac3fa60e0848d784a6dd461da6.png

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 }

69c5a8ac3fa60e0848d784a6dd461da6.png

cURL选项设置的顺序

不管是curl_setopt()单发还是curl_setopt_array()批量,cURL的选项总是设置一个生效一个,而设置好的选项立刻就会影响cURL在设置后续选项时的行为。

例如CURLOPT_SAFE_UPLOAD就和CURLOPT_POSTFIELDS的行为有关。如果先设置CURLOPT_POSTFIELDS再设置CURLOPT_SAFE_UPLOAD,那么后者的约束作用就不会生效。因为设置前者时cURL就已经把数据实际的识读处理完毕了!

cURL有那么几个选项存在这种坑,务必小心。还好这种存在“依赖关系”的选项不多,机制也不复杂,简单处理即可。我的方法是先批量设置所有的选项,然后直到curl_exec()的前一刻才用curl_setopt()单发设置CURLOPT_POSTFIELDS。

实际上在curl_setopt_array()用的数组中,保证CURLOPT_POSTFIELDS的位置在后边也是可靠的。PHP的关联数组是有顺序保障的,我们也可以假设curl_setopt_array()内部的执行顺序一定是从头到尾按顺序[注A],所以尽可放心。

我的做法只是在代码表现上加个多余的保险,突出强调顺序的重要性防以后手贱。

命名空间

PHP 5.2或以下的版本没有命名空间。代码中用到了空间分隔符\就会引发解析器错误。要照顾PHP 5.2其实容易想,放弃命名空间即可。

要注意的反倒是有命名空间的PHP 5.3+。无论是调用CURLFile还是用class_exists()判断CURLFile的存在性,都推荐写成\CURLFile明确指定顶层空间,防止代码包裹在命名空间内的时候崩掉。

最后兼容各版本代码如下:

69c5a8ac3fa60e0848d784a6dd461da6.png

1 <?php

2

3 /* http://localhost/upload.php:

4 print_r($_POST);

5 print_r($_FILES);

6 */

7

8 $ch = curl_init();

9

10 $filePath = '/home/vagrant/test.png';

11 $data = array('name' => 'Foo', 'file' => '@' . $filePath);

12

13 //兼容5.0-5.6版本的curl

14 if (class_exists('\CURLFile')) {

15 $data['file'] = new \CURLFile(realpath($filePath));

16 } else {

17 if (defined('CURLOPT_SAFE_UPLOAD')) {

18 curl_setopt($ch, CURLOPT_SAFE_UPLOAD, FALSE);

19 }

20 }

21

22 curl_setopt($ch, CURLOPT_URL, 'http://localhost/test/curl/load_file.php');

23 curl_setopt($ch, CURLOPT_POST, 1);

24 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

25

26 curl_exec($ch);

27 ?>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

netty 客户端断开 异常处理_netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理》发数据方式》...

小傅哥 | https://bugstack.cn 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获。专注于原创专题案例编写&#xff0c;目前已完成的专题有&#xff1b;Netty4.x实战专题案例、用Java实现JVM、基于JavaAgent的全链路监控、手写RPC框架、架构设计专题案例、源码分析等。你…

Java Windows注销用户,中止Windows从Java注销

EDIT2对于那些跟随讨论的人&#xff0c;我留下了我的第一个答案&#xff0c;但似乎他们没有工作。首先找到我的真正解决方案好吧&#xff0c;所以我认为这实际上有效&#xff0c;但它并不完全可以接受&#xff0c;因为它使用了受限制的API部分(但它自Java 1.3以来就存在并且仍然…

MySQL和mq一致性,Mysql与Redis一致性问题

缓存一致性产生背景如果每次频繁的访问数据库的时候&#xff0c;虽然查询底层使用B树索引 但还会做磁盘的IO操作&#xff0c;可能会对数据库的压力非常大。所以为了能够减轻数据库的访问压力&#xff0c;会使用一些缓存实现减轻数据库的压力。比如 Redis、es、ehcache、oscache…

clustalw序列比对_序列比对(二)

Homology is the central concept for all of biology.——David Wake. Science, 1994前言正如前面引用的这句话&#xff0c;同源性是生物学中的核心问题。研究序列的同源性问题&#xff0c;就要用到序列比对的工具&#xff0c;上一篇笔记简单介绍了序列比对的原理&#xff0c;…

pr渲染程序选哪个_PR的bug你遇到过几个?

哈喽 大家好呀 我是K同学&#xff01;对于Pr的用户来讲&#xff0c;Pr有很多BUG让人很奔溃&#xff0c;不仅Pr奔溃了&#xff0c;人都奔溃了作为Pr的老用户&#xff0c;今天我就来盘点下&#xff0c;我遇到过Pr的变态BUG第一个Pr不支持微软输出法这是我使用Pr遇到的第一个BUG&a…

java model 中文乱码,java传值乱码解决方法

在做JavaWeb时&#xff0c;总是时不时的会遇到中文传值乱码问题&#xff0c;在你把所有”ISO-8859-1”改成“UTF-8”发现还是没什么用。于是我就找到了一个百试百灵的方法(至少目前我是)&#xff0c;就是强行转换成“UTF-8”编码。看代码&#xff1a;RequestMapping("/suc…

检查一列数据的重复项 vba_提取重复值,但字典不是重点。

本例的问题描述&#xff1a;1&#xff1a;源数据与提取的结果在同一个工作表里面&#xff1b;2&#xff1a;提取K、M、O、Q列里面不重复的数据(注意&#xff0c;数据列里面有空白的行)&#xff1b;3&#xff1a;把提取出来的结果放在A2单元格的下方&#xff0c;不能有空白行&am…

swiper怎么让不会回弹,为什么我的滚动条拉上拉下都会回弹呢?

其它都是正常的&#xff0c;就是拉上去拉下来自己又回弹回去了&#xff0c;拉不到最底部也拉不到最顶部&#xff0c;拉来拉去都会是这样的category/index.vueimport CategoryHeader from "./header";import CategoryTab from "./tab";import CategoryConte…

异构服务器 微服务_Spring Cloud Alibaba Sidecar 多语言微服务异构

Spring Cloud Alibaba Sidecar 介绍自 Spring Cloud Alibaba 2.1.1 版本后增加了 spring-cloud-alibaba-sidecar 模块作为作为一个代理的服务来间接性的让其他语言可以使用spring cloud alibaba等相关组件。通过与网关的来进行路由的映射&#xff0c;从而可以做到服务的获取&am…

matlab教程点语言,编程语言 / Matlab教程_电脑教程学习网( 5 )

逐次超松弛方法(SOR方法)求解方程组日期&#xff1a;2014-09-26 21:03:34点击&#xff1a;370好评&#xff1a;0#includeiostream.h//逐次超松弛方法(SOR方法)求解方程组 #includemath.h #includeiomanip.h #define n 3 void main() { double A[n][n]{{5,2,1},{-1,4,2},{2,-3,1…

sql 以a开头的所有记录_SQL开发与数据库管理笔记

简介&#xff1a; SQL开发与数据库管理笔记&#xff0c;看过的都说好&#xff01;原创&#xff1a; 丶平凡世界文章链接&#xff1a;https://mp.weixin.qq.com/s/Y9TmoHOyh7To7jUrMulvEw一、开发管理篇1.按姓氏笔画排序Select * From TableNameOrder By CustomerNameCollate Ch…

zynq中mgtx应用_基于ZYNQ的UCOS移植(TCP通讯)

周五在某小徐处借到了一块Zedboard开发板&#xff0c;平时在公司没有机会做SDK开发的笔记&#xff0c;今天就趁着这块开发板简要记录一些SDK的基本操作。一、功能简介通过第三方库创建SDK工程在ZYNQ-UCOS中实现TCP echo通讯二、配置需求操作系统Windows 10(64位)开发环境SDK 20…

算法描述怎么写_管件材料描述怎么写

通过以上及其我们了解到了管道上不同的管道元件&#xff0c;包括&#xff1a;弯头、三通、异径管、管帽等。但在材料等级表中如何清楚的描述它们的特性&#xff0c;至关重要&#xff0c;因为这涉及材料采购是否正确。以下主要介绍管件材料描述的写法&#xff1a;①弯头 ②DN15~…

linux复制文件通信方式,Linux分布式文件拷贝

在开发过程中总会遇到这种情况&#xff0c;就是需要将一个文件从一个机器拷贝到其他的很多台机器中&#xff0c;最简单的方法是用U盘拷出来再一个一个机器的插进去拷贝&#xff0c;另一张方法则是利用飞鸽传书或者QQ等工具传输&#xff0c;但是都不是很方便&#xff0c;因为每次…

安装linux修复系统文件夹,误删除 Linux 系统文件了?这个方法教你解决

误删除linux系统文件了?不用急&#xff0c;本文将给你一个恢复linux文件的方法&#xff0c;让你轻松应对运维中的各风险问题。方法总比问题多~说在前面的话针对日常维护操作&#xff0c;难免会出现文件误删除的操作。大家熟知linux文件系统不同win有回收站&#xff0c;删除后的…

linux tmux 详细教程,Linux下的神器介绍之Tmux分屏器

前言我们为什么需要分屏器呢&#xff1f;对于这个问题&#xff0c;我想大家肯定都有自己的看法。主流的观点是这样的&#xff0c;对于生活在Linux下的人(开发人员、运维人员、普通爱好者)都不可避免的使用终端模拟器(比如&#xff0c;gnome-terminal)去执行一些命令或者脚本。但…

laravel created_at 时间戳_使用 HTTP 测试测试 Laravel 中间件

文章转发自专业的Laravel开发者社区&#xff0c;原始链接&#xff1a;https://learnku.com/laravel/t/34002在本文中&#xff0c;我将展示一个使用 HTTP 测试中间件的实例。HTTP 级测试更能适应变化&#xff0c;可读性更强。在最近与 Adam Wathan 和 Taylor Otwell 合拍的《全栈…

动物识别专家系统python_Python有哪些作用?

Python是什么呢&#xff1f;Python是一种全栈的开发语言&#xff0c;如果能学好Python&#xff0c;前端、后端、测试、大数据分析、爬虫等这些工作你都能胜任。那Python有哪些作用呢&#xff1f;Python主要有以下四大主要应用&#xff1a;网络爬虫网站开发人工智能自动化运维接…

linux mint图标大小,Cinnamon:LinuxMint 15桌面设置小技巧

touchwiz自身也在做不断的革新&#xff0c;例如7屏分页&#xff0c;桌面切换3d效果&#xff0c;增强型的下拉菜单设置等。win10多桌面最多可以支持7个桌面开启&#xff0c;而且win10切换多桌面是有快捷键的&#xff0c;可以帮助用户迅速切换或创建以及关闭多桌面。切换方法一&a…

操作系统源代码_国产操作系统“之光”?Windows XP绝密源代码泄露,BT种子已在网上疯传...

微软的Windows操作系统是目前使用人数最多、覆盖最广的桌面操作系统&#xff0c;从安全角度来看&#xff0c;其系统源代码对于公众而言可以说是绝密。不过......现在......&#xff0c;黑客在4Chan平台上以BT种子文件的形式在线泄漏了多个旧Windows版本的源代码&#xff0c;包括…